Python-Tkinter中无法获取按键事件的解决方法

3

当我按上箭头、下箭头、左箭头或右箭头时,我正在模拟“下降”动作。我认为它会移动,但是当我打开Tkinter时,我没有得到任何响应。似乎它无法在sleep()时间和Tk.after()时间内获取任何按键。我该如何解决这个问题?

这是我使用Python-2.7和Tkinter的代码。

from Tkinter import *
import msvcrt,time
root=Tk()
c=Canvas(root,height=900,width=700)
c.pack()
p0=(450,450)
p1=(460,460)
a1=c.create_oval(p0,p1,fill='red')
def foo():
        if msvcrt.kbhit():
            key=msvcrt.getch()
            if key=='P':
                c.move(a1,0,5)
                a1.itemconfig(fill='yellow')
            elif key=='H':
                c.move(a1,0,-5)
                a1.itemconfig(fill='blue')
            elif key=='K':
                c.move(a1,-5,0)
                a1.itemconfig(fill='white')
            elif key=='M':
                c.move(a1,5,0)
                a1.itemconfig(fill='green')
            elif key =='\x1b':
                root.exit()
            c.after_cancel(m)
            c.pack()
            sleep(0.5)
            #root.update()
            foo()
        else:
            c.move(a1,0,2)
            m=c.after(1000,foo)
            #sleep(0.5)
            #root.update()
            c.pack()
foo()
root.mainloop()

为什么在tkinter程序中使用msvcrt.getch()?无论如何,您是正确的,当程序处于睡眠状态时不会识别任何键。这就是为什么您永远不应该在GUI程序的主线程中调用sleep的原因。 - Bryan Oakley
抱歉,我是一名初学者,不理解那个...我成功地在Tkinter中使用了msvcrt.getch()而无需睡眠,它有响应。这就是为什么我尝试制作俄罗斯方块程序的原因。谢谢您的回答 :) - Insomnia
1个回答

4

不要混合使用Tkinter和msvcrt,最好使用Tkinter的<Key>事件来捕获按键操作

这是一个修改过的版本,使用了Key事件:

from Tkinter import *

def foo(event):
    global m

    key = event.char
    if key.upper() == 'P':
        c.move(a1,0,5)
        c.itemconfig(a1, fill='yellow')
    elif key.upper() == 'H':
        c.move(a1,0,-5)
        c.itemconfig(a1, fill='blue')
    elif key.upper() == 'K':
        c.move(a1,-5,0)
        c.itemconfig(a1, fill='white')
    elif key.upper() == 'M':
        c.move(a1,5,0)
        c.itemconfig(a1, fill='green')
    elif key == '\x1b':
        root.destroy()
    c.after_cancel(m)
    m = c.after(1000, move)

def move():
    c.move(a1, 0, 2)
    m = c.after(1000, move)

root = Tk()
c = Canvas(root,height=900,width=700)
c.pack()
p0 = (450,450)
p1 = (460,460)
a1 = c.create_oval(p0,p1,fill='red')
m = root.after(1000, move)
root.bind('<Key>', foo)
root.mainloop()

@Insomnia,在GUI线程中使用sleep不是一个好主意。这会使GUI无响应。通过在事件处理程序中调用sleep,GUI线程被卡住,无法处理其他挂起的事件。 - falsetru
@失眠症:当你调用sleep时,你的程序就会进入睡眠状态。在睡眠期间,它不会执行任何操作,包括响应事件。 - Bryan Oakley
是的,而且after()不会延迟我的按键响应,所以它可以立即响应,对吧? - Insomnia
@Insomnia,可以的。 - falsetru
@Insomnia,请发布一个单独的问题。 - falsetru
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接