Need Function To Run As Long As Button Widget Pressed

jepler at unpythonic.net jepler at unpythonic.net
Wed Nov 20 21:10:44 EST 2002


I spot several errors in your program.

>       self.buttonGo = Button(frame, text= "Print", command=self.Go)

The command of a button only fires after a mouse button is pressed and
then released inside the widget.  So self.Go will be called too late, after
the button is released.  Instead, make "go" be called when the button is
first pressed, on the <Button-1> event.

>   def IsPressed(event):

The first argument of each method must be the 'self' argument.  All events
(as opposed to a button's command) have an event parameters in the
callback.  You need
    def IsPressed(self, event): ...

>          self.after(10, self.Go())

You want to perform the function "Go" after 10ms, not the function returned
by "Go".  Instead, write
          self.after(10, self.Go)

Also, I don't see how your 'self' gets an 'after' attribute (method) since
it doesn't derive from BaseWidget.

You might consider using "after_idle(self.Go)".  Instead of waiting 10ms,
it will wait until all events have been serviced, then call Go.

Or, depending on your situation, you could write 'Go()' as a function which
calls "self.frame.update()" from time to time.  "update()" handles peding
events and then returns.  This way, you can write your processing loop in
the straightforward way:
	def go():
		for i in range(1000):
			process_a_little(i)
			self.frame.update()
instead of the cumbersome (and possibly wrong) way:
	def go():
		i = self.i
		if i < 1000:
			process_a_little(i)
			self.afterid = self.frame.after_idle(go)
			self.i = i + 1

My solution also uses a label instead of a button since it doesn't use any
of the button's builtin bindings anyway (mostly, these implement the
mechanics of -command).  It still uses plain after().  Otherwise, it uses
the suggestions I've made here.

Jeff



from Tkinter import *

class App:
    interval = 100

    def __init__(self, master):
        self.button = Label(master, text="Go", relief="raised")
        self.button.bind("<Button-1>", self.press)
        self.button.bind("<ButtonRelease-1>", self.release)
        self.button.bind("<Leave>", self.release)
        self.button.pack()

        self.status = 0
        self.afterid = None
        self.after = master.after
        self.after_cancel = master.after_cancel

    def press(self, ev):
        self.button.configure(relief="sunken")
        self.status = 1
        if self.afterid is None:
            self.afterid = self.after(self.interval, self.go)

    def release(self, ev):
        self.button.configure(relief="raised")
        if self.afterid is not None:
            self.after_cancel(self.afterid)
            self.afterid = None

    def go(self):
        print "Working"
        self.afterid = self.after(self.interval, self.go)

root = Tk()
app = App(root)
root.mainloop()





More information about the Python-list mailing list