[Tutor] tkinter events: <B1-Motion>

Zsiros Levente zslevi at sch.bme.hu
Tue Aug 22 12:05:30 CEST 2006


You're right, that I pressed reply instead of reply-to-all, so the list 
didn't see my response. But this way you got my mail twice. Isn't that 
annoying? Other maillist servers used to use the reply-to tag in the 
message header.

Luke Paireepinart wrote:

> Zsiros Levente wrote:
>
>> [snip code]
>> *def* handler(event):
>>     *if* buttonpressed == 1 :
>>         /#if the mousebutton is pressed and moved, circles should 
>> appear, but they do not/
>>         can.create_oval(event.x-r, event.y-r, event.x+r, event.y+r, 
>> fill="orange")
>>     lab.config(text='buttonpressed=' + str(buttonpressed) )
>>
>> *def* press(event):
>>     buttonpressed=1
>>     lab2.config(text=buttonpressed)
>>     
>> *def* release(event):
>>     buttonpressed=0
>>     lab2.config(text=buttonpressed)   
>> [snip code]
>> /#global buttonpressed/
>> buttonpressed=0
>
>
> I think you're misunderstanding what global variables are.
>
> Take the following example:
>
> #--- code
> a = 0
> def b():
>    print a
> b()
>
> #--- output
> 0
> #---
> the function 'b' can see the variable 'a'. ok so far.
>
> now take this example.
>
> #--- code
> a = 0
> def b():
>    a = 1
>    print a
> b()
> print a
>
> #--- output
> 1
> 0
> #---
> in this case, 'a' is assigned to, but it's a local variable called 'a' 
> and not the one I think you expect it to assign to.
> so after 'b' is done the value of the 'a' outside of the scope of the 
> function is still 0.
> in your press and release events you assign values to 'buttonpressed' 
> before you use them,
> and because of this, the same thing happens as in our second example: 
> a local variable named
> 'buttonpressed' is created with the value 0 or 1 assigned to it 
> (depending on the function you're in.)
> that works fine, and it sets the label's text value accordingly.  But, 
> since it's a local variable and the
> functions aren't actually modifying the global 'buttonpressed', the 
> 'buttonpressed' that you're checking for
> in your 'handler' function is always going to be 0.  That's why your 
> oval code is never drawn.
>
> Rather than messing with global variables, which are for the most part 
> evil creatures,
> as we've witnessed so far here, I'd recommend using a class.
> I wrote the class I would use for you so you can see it.
> It's commented, but if you need any more help than the comments feel 
> free to write me back.
> Just be sure to use the reply-all button so the whole list can see the 
> response.
> -Luke
> (note: code attached)
>
>------------------------------------------------------------------------
>
>#!/usr/bin/python
>
># This program implements <B1-motion>.  it was originally written by
>#Zsiros Levente.  all rights of this modified version go to him :)
>
>from Tkinter import *
>
>class ButtonHandler(object):
>    def __init__(self):
>        #our self.mousedown variable is what we'll use to check the state
>        #of the button, since we're going to be passing a copy of 'self'
>        #around, we don't have to deal with scoping of the variables.
>        #I.E. self.mousedown is global to functions in the class
>        #that accept a 'self' argument.
>        self.mousedown = 0
>        
>        #we make the window normally. note all these are 'self' variables
>        #so we can change them easily elsewhere in the class.
>        self.root = Tk()
>        self.root.geometry('600x500+200+200')
>        self.label = Label(self.root, text=str(self.mousedown))
>        self.can = Canvas(self.root, width='500', height='400', bg='white')
>        #lambda is a way we can add extra arguments to a function.
>        #since the callback of bound events is only a single argument,
>        #we use 'lambda x' to get the 'event' instance, and pass it
>        #along with another string identifying which event it came from.
>        #this may or may not be necessary, but it's cool and it
>        #makes the handler function make more sense.
>        #also, we only need one handler function this way.
>        self.can.bind("<Motion>",lambda x:self.handler(x,'motion'))
>        self.can.bind("<Button-1>",lambda x:self.handler(x,'press'))
>        self.can.bind("<ButtonRelease-1>",lambda x:self.handler(x,'release'))
>        self.label.pack()
>        self.can.pack()
>        self.root.mainloop()
>        
>    def handler(self,event,x):
>        #the first two clauses of the if-elif branch implement your
>        #'press' and 'release' functions.
>        if x == 'press':
>            self.mousedown = 1
>        elif x == 'release':
>            self.mousedown = 0
>        elif x == 'motion':
>            if self.mousedown:
>                #you could do something really cool here, like store the time
>                #that the button was last pressed, and increase the radius of the circle
>                #depending on how long it's been since then.
>                r = 5
>                self.can.create_oval(event.x-r, event.y-r, event.x+r, event.y+r, fill="orange")
>	self.label.config(text=str(self.mousedown))
>        
>
>#we create an instance of the class which automatically
>#calls the '__init__' method.
>x = ButtonHandler()
>  
>



More information about the Tutor mailing list