-1

When I run my current program, the triangle shape on this program is only moving once when I press the button. I want my triangle shape to be moving automatically one pixel per unit time, but I am not sure how to make this work.

So far, while doing this program, I still cannot figure out which bits of classes and definitions go where and what to do with such classes and definitions to make them work like what I intended to, as written above.

import tkinter as tk
from tkinter import PhotoImage
from tkinter import *
import time

counter = 0
running = False   

class triangle():
    def trianglemovedefine(move_x, move_y):
        canvas.move (triangle3, move_x, move_y)

    def trianglemove():
        triangle.trianglemovedefine(1, 0)

def moveitboi(justmoveit):
    def count(): 
        if running: 
            global counter 
            justmoveit = lambda:triangle.trianglemove()
            #My "per unit time" adjusted to per 1000 microseconds
            justmoveit.after(1000, count)  
            counter += 1
    count()

def Start(justmoveit):
    global running
    running=True
    moveitboi(justmoveit)

root = tk.Tk()
root.geometry("960x600")

label_toptitle = tk.Label(root, text="Program Name", font=(None, 40),)
label_toptitle.grid(row=0, columnspan=3)

label_desc = tk.Label(root, image=pixel, compound="center", width=900, font=(None, 14),
                                          padx=20, pady=10, text=description)

label_desc.grid(row=1, columnspan=3)

canvas = tk.Canvas(width=960, height=300, bg='white')
canvas.grid(row=2, column=0, columnspan=3)

for linecounter in range(49):
        newtextbit = linecounter + 1
        if (newtextbit + 3) % 4 == 0 and newtextbit != 49:
                canvas.create_text((linecounter * 16 + 80), 90,
                                           fill="darkblue",
                                           font="Times 10 bold",
                                           text=newtextbit)
        if (newtextbit + 3) % 4 == 0:
                canvas.create_line(((linecounter * 16 + 80)), 40, ((linecounter * 16 + 80)), 70,
                                           width=1,
                                           fill="black"
                                           )
        else:
                canvas.create_line(((linecounter * 16 + 80)), 50, ((linecounter * 16 + 80)), 70,
                                           width=1,
                                           fill="black"
                                           )
canvas.create_line(73, 70, 860, 70,
                                   width=2,
                                   fill="black"
                                   )
#The Triangle
triangle3 = canvas.create_polygon(75, 25, 86, 25, 80, 40, fill ='red')

f1 = tk.Frame(root, width=70, height=30)
f1.grid(row=3, column=0, sticky='W')

button_record = tk.Button(f1,
                          text="Record",
                          compound="top",
                          command=lambda:triangle.trianglemove(),
                          )

button_record.pack(side='left', padx=140)


root.mainloop()
martineau
  • 119,623
  • 25
  • 170
  • 301
Ron Zhang
  • 195
  • 1
  • 3
  • 17
  • This sort of thing is usual done by using the universal widget method [`after()`](http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/universal.html) which allows the "scheduling" of updates to the display to occur after a specified delay. There are many `tkinter` answers here that show how to do this, so I suggest you do a little more research. Answer to questions about how to making clocks or doing animation are often good candidates. – martineau Oct 17 '18 at 20:38
  • I do have the `after()` widget, but my problem is how to get my `after()` widget to work as I intended. So far, pressing the button only pushes the triangle once manually. I tried waiting for program to move triangle again by one second, but I didn't see anything moving. – Ron Zhang Oct 17 '18 at 20:39
  • @martineau I tried looking for some of those types of questions, but I couldn't find any. Any recommended URL links I should look at? – Ron Zhang Oct 17 '18 at 20:42
  • 1
    Your `moveitboi()` function only calls `after()` once. In needs to call it over-and-over to keep things going. Give me a minute and I'll try to find a good one for you... – martineau Oct 17 '18 at 20:42
  • Okay, but I currently do not know how to make a function call the `after()` widget over and over. I request some code solution. – Ron Zhang Oct 17 '18 at 20:45
  • Here's one for the question [Tkinter animation will not work](https://stackoverflow.com/a/28549748/355230). The basic idea is you call `after()` again in the function that it just called. In the linked answer `update_label_image()` which is called *by* `after()` itself calls `after()` to schedule a subsequent call to itself. – martineau Oct 17 '18 at 20:48

1 Answers1

2

After making fairly extensive changes to the code in your question, eventually I was able to get something runnable enough to illustrate how to implement the suggestion I posted in comments about how to do what you want with the universal after() widget method.

Note how the last line of moveitboi() calls after() to schedule another call to itself after the specified delay.

While making the changes I also attempted to make the code mostly follow the PEP 8 - Style Guide for Python Code suggestions. I strongly suggest you read it and do the same when writing your own code in the future.

import tkinter as tk

class Triangle:
    def __init__(self, canvas, *points, fill=''):
        self.canvas = canvas
        self.obj_id = canvas.create_polygon(*points, fill=fill)

    def move(self, move_x, move_y):
        self.canvas.move(self.obj_id, move_x, move_y)

    def move_right(self):
        self.move(1, 0)


def moveitboi(parent, marker):
    global counter

    if running:
        marker.move_right()
        counter += 1

    # Call this func again after delay.
    parent.after(1000, moveitboi, parent, marker)

def start(parent, marker):
    global running

    if not running:
        running = True
        moveitboi(parent, marker)  # Start triangle position updates.


root = tk.Tk()
root.geometry("960x600")

counter = 0
running = False

label_toptitle = tk.Label(root, text="Program Name", font=(None, 40),)
label_toptitle.grid(row=0, columnspan=3)

# Left out because I don't have the "pixel" image.
#label_desc = tk.Label(root, image=pixel, compound=tk.CENTER, width=900, font=(None, 14),
#                      padx=20, pady=10, text=description)

canvas = tk.Canvas(root, width=960, height=300, bg='white')
canvas.grid(row=2, column=0, columnspan=3)

for linecounter in range(49):
    newtextbit = linecounter + 1
    xposn = linecounter*16 + 80

    if (newtextbit + 3) % 4 == 0 and newtextbit != 49:
        canvas.create_text(xposn, 90, fill="darkblue", font="Times 10 bold",
                           text=newtextbit)
    if (newtextbit + 3) % 4 == 0:
        canvas.create_line(xposn, 40, xposn, 70, width=1, fill="black")
    else:
        canvas.create_line(xposn, 50, xposn, 70, width=1, fill="black")  

canvas.create_line(73, 70, 860, 70, width=2, fill="black")

# Global triangle.
triangle3 = Triangle(canvas, 75, 25, 86, 25, 80, 40, fill='red')

f1 = tk.Frame(root, width=70, height=30)
f1.grid(row=3, column=0, sticky='W')

button_record = tk.Button(f1, text="Record", compound="top",
                          command=lambda: start(root, triangle3))
button_record.pack(side='left', padx=140)

root.mainloop()

Here's a screenshot showing the moved position of the red marker several seconds after the Record button was clicked:

screenshot after clicking Record button

martineau
  • 119,623
  • 25
  • 170
  • 301
  • Thanks for the link to the PEP 8 Style Guide. I presume PEP 8 Style Guide is a set of guidelines for writing efficient Python code, isn't it? – Ron Zhang Oct 18 '18 at 00:33
  • 1
    Ron: Glad to hear you found my answer useful. PEP 8 is not so much about efficiency as it is about writing readable code—which makes it easier to maintain and for others (including yourself later on) to understand what it's doing. – martineau Oct 18 '18 at 00:40
  • 1
    P.S. I don't strictly follow PEP 8, just mostly. Use your own judgement—it just guidelines (from some very smart people) and it even says something along those lines near the [beginning](https://www.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds). – martineau Oct 18 '18 at 00:50