user2658538
user2658538

Reputation: 367

Event binding arrow keys python Tkinter

I am trying to make a simple game in tkinter, and I need to bind the left/right arrow keys to a class method. The method also accepts an argument. I have done the binding, but when I click the arrow keys, nothing moves. I tried adding a print statement to the method, and when I click the keys, nothing prints, so the method isn't getting called. I don't think the binding is working, but I'm not sure how to fix it!

Also, is there a way to keep running a bound method if the user holds the bound key? Like click and holding the left key and having the method keep running over and over until the user lets go.

Thanks.

from Tkinter import *
    from math import *
    global radius
    radius=175
    root=Tk()
    c=Canvas(root,width=600,height=600)
    c.pack()
    c.configure(scrollregion=(-300, -300, 300, 300))
    c.create_oval((-40,-40,40,40),fill="Yellow",outline="Yellow")
    def findcoords(angle,radius):
            #cos,sin
            a=cos(radians(angle))
            b=sin(radians(angle))
            return ((a*radius),(b*radius),(a*radius),(b*radius))

    def createOutline(radius):
        t=0
        while t<=360:
            c.create_rectangle(findcoords(t,radius))
            t+=.01
    class World():
        def __init__(self,canvas,img=None,size=20,angle=90):
            self.size=size
            self.angle=angle
            self.position=self.findcoord()
            self.canvas=canvas
            if img!=None:
                self.img=img
                self.current=c.create_image(self.position,image=self.img)
            else:
                self.current=c.create_oval(self.position,fill="Blue",outline="Blue")
            c.bind('<Left>',lambda event,arg=.1:self.move(event,arg))
            c.bind('<Right>',lambda event,arg=-.1:self.move(event,arg))
        def findcoord(self):
            #cos,sin
            a=cos(radians(self.angle))
            b=sin(radians(self.angle))
            return (((a*radius)-self.size),((b*radius)-self.size),((a*radius)+self.size),((b*radius)+self.size))           
        def move(self,n):
            self.angle+=.1
            self.position=self.findcoord()
            self.canvas.coords(self.current,self.position)

    createOutline(175)
    a=World(c)



    root.mainloop()

Upvotes: 0

Views: 10216

Answers (2)

Dyson L.
Dyson L.

Reputation: 21

Ditch the lambdas for class functions. Instead of

lambda event,arg=.1:self.move(event,arg)

lambda event,arg=-.1:self.move(event,arg))

do

left

and

right

respectively. Make sure to write corresponding class functions with the event parameter.

I also can't quite understand your code. In move() (class World's method), you set the parameter n, but you never use it. Try cleaning up your code a bit, or adding comments to explain what exactly you are doing.

Upvotes: 2

Hez
Hez

Reputation: 11

Try setting your focus using:

c.focus_set()

You could also bind the keys to your root so

root.bind('<Left>',lambda event,arg=.1:self.move(event,arg))
root.bind('<Right>',lambda event,arg=-.1:self.move(event,arg))

It's just looking like you don't have focus on the frame so the keyboard presses aren't getting sent to the correct frame.

As far as holding goes you can have the event continue until the key is released. Formatting for releasing keys goes like this:

c.bind("<KeyRelease-left>", onkeyrelease_of_key)

replacing the onkeyrelease_of_key with your event.

Upvotes: 1

Related Questions