line order

Fredrik Lundh fredrik at pythonware.com
Sun Nov 20 09:29:09 EST 2005


Ben Bush wrote:

> I run the following code and the red line and black line show at the
> same time. is there anyway to show the red line first, then the black
> line? for example, after I click the 'enter' key?
>
> from Tkinter import *
> tk = Tk()
> canvas = Canvas(tk, bg="white", bd=0, highlightthickness=0)
> canvas.pack(fill=BOTH, expand=YES)
> canvas.create_line(100, 200, 350, 200, arrow=LAST,fill='red')
> canvas.create_line (100, 0, 100, 200, arrow=FIRST)
> tk.mainloop()

Tkinter uses background "tasks" to update the screen.  Such tasks are
called by Tkinter's event processning system, so nothing happens until
you hand control over to Tkinter.  You can use update or update_idle-
tasks to explictly process all pending events/background tasks:

    canvas.create_line(100, 200, 350, 200, arrow=LAST,fill='red')
    canvas.update_idletasks() # run all pending background tasks
    wait_for_enter_key() # e.g. using raw_input()
    canvas.create_line (100, 0, 100, 200, arrow=FIRST)

However, if you add this to a larger Tkinter program, you'll lock up the GUI
when you're waiting for the enter key.  A better approach is to hand control
over to Tkinter, and ask it to draw another item whenever the user presses
return:

    canvas = Canvas(tk, bg="white", bd=0, highlightthickness=0)
    canvas.pack(fill=BOTH, expand=YES)

    def draw(event):
        ...

    canvas.focus_set() # make sure we have focus
    canvas.bind("<Return>", draw)

    tk.mainloop()

the binding means that whenever the user presses the Return key when the
Canvas has focus, Tkinter will call the draw callback.  you can use a simple
counter to keep track of the items:

    count = 0

    def draw(event):
        global count
        if count == 0:
            canvas.create_line(100, 200, 350, 200, arrow=LAST,fill='red')
        elif count == 1:
            canvas.create_line(100, 0, 100, 200, arrow=FIRST)
        count = count + 1

or you can add a simple wrapper

    def generator_callback(func):
        gen = func()
        def callback(event):
            try:
                gen.next()
            except StopIteration:
                pass
        return callback

and use a generator function to implement the callback:

    def draw():
        canvas.create_line(100, 200, 350, 200, arrow=LAST,fill='red')
        yield None
        canvas.create_line(100, 0, 100, 200, arrow=FIRST)
        # we're done

    canvas.bind("<Return>", generator_callback(draw))

hope this helps!

</F> 






More information about the Python-list mailing list