[Tutor] tkinter events: <B1-Motion>

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


Zsiros Levente wrote:

>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.
>>
>>    
>>
>Yes, others already mentioned that.
>  
>
You didn't notice that, because first I accidentally sent the code to 
other thread (self-modification; of which I have three already :-X )

>  
>
>>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()
>> 
>>
>>    
>>
>
>_______________________________________________
>Tutor maillist  -  Tutor at python.org
>http://mail.python.org/mailman/listinfo/tutor
>  
>



More information about the Tutor mailing list