tkinter (python): assign class method to a key

纵然是瞬间 提交于 2019-12-20 03:11:52

问题


In my simple code, a red ball is falling down in a straight line (that's working). When I push the right arrow key, I want the ball to also move in right direction. This is not working, however. What am I doing wrong?

from tkinter import *

root = Tk()

canvas = Canvas(root, height=400, width=500, background='black')
canvas.pack()


class Bird:
    def __init__(self, canvas, coords):
        self.canvas = canvas
        self.coords = coords
        self.bird = canvas.create_rectangle(coords, fill='red')

    def gravity(self):
        self.canvas.move(self.bird, 0, 10)
        self.canvas.after(200, self.gravity)

    def moveRight(self, event):
        self.canvas.move(self.bird, 10, 0)
        self.canvas.after(200, self.moveRight)

bird = Bird(canvas, (100, 100, 110, 110))

bird.gravity()

canvas.bind('<Right>', bird.moveRight)

root.mainloop()

I have another additional question:

Is it possible to call this "after"-function or a similar function for the whole canvas instead of the two methods separately?

If you see any other flaws with my code plz let me know!

Thanks!


回答1:


You must bind the right key to the canvas inside the class, and set the focus on the canvas:

from tkinter import *

root = Tk()

canvas = Canvas(root, height=400, width=500, background='black')
canvas.pack()


class Bird:
    def __init__(self, canvas, coords):
        self.canvas = canvas
        self.coords = coords
        self.bird = canvas.create_rectangle(coords, fill='red')
        self.canvas.bind('<Right>', self.moveRight)
        self.canvas.focus_set()

    def gravity(self):
        self.canvas.move(self.bird, 0, 10)
        self.canvas.after(200, self.gravity)

    def moveRight(self, event=None):
        self.canvas.move(self.bird, 10, 0)
        self.canvas.after(200, self.moveRight)


bird = Bird(canvas, (100, 100, 110, 110))

bird.gravity()

root.mainloop()



回答2:


The problem you are facing is that you are binding keyboard events, but the events can only work if the widget with the bindings has the keyboard focus. You can give the canvas the keyboard focus with focus_set():

canvas = Canvas(root, height=400, width=500, background='black')
canvas.focus_set()

Is it possible to call this "after"-function or a similar function for the whole canvas instead of the two methods separately?

Yes. Your binding can call any function you want. If you expect to have more than one object and you want them all to move at the same time, you can move them all from a function.

First, remove the call to after from moveRight. Next, define a global function that calls moveRight for every object. For example:

def move_them_all():
    bird1.moveRight()
    bird2.moveRight()
    something_else.moveRight()
    self.canvas.after(1000, move_them_all)
...
canvas = Canvas(root, height=400, width=500, background='black')
...
canvas.bind('<right>', move_them_all)


来源:https://stackoverflow.com/questions/46461706/tkinter-python-assign-class-method-to-a-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!