【问题标题】:python-fail to get keypress in Tkinterpython-无法在 Tkinter 中获取按键
【发布时间】:2016-03-19 09:52:52
【问题描述】:

当我按下 UpArrow、DownArrow、LeftArrow 或 RightArrow 时,我正在模拟一个“下降”动作。我想它会移动,但是当我打开 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
  • 对不起,我是一个初学者,不明白...我设法在 Tkinter 中使用 msvcrt.getch() 而不睡觉,它响应了。这就是我尝试制作俄罗斯方块程序的原因.谢谢你的回答:)

标签: python python-2.7 tkinter


【解决方案1】:

与其混合使用Tkinter和msvcrt,不如use Tkinter's <Key> event to catch keypress

这是一个使用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()

【讨论】:

  • 非常感谢您的解决方案。实际上我已经通过使用'Key'解决了这个问题,但我不明白为什么使用'after'无法捕捉到响应。当我尝试调试时我发现在“睡眠”期间,Tkinter 可以捕捉到按键但无法立即响应。你能解释一下原因吗?
  • @Insomnia,在 GUI 线程中使用 sleep 不是一个好主意。它会使 GUI 无响应。通过在事件处理程序中调用sleep,GUI线程卡在那里,无法处理其他未决事件。
  • @Insomnia:当您调用 sleep 时,您的程序会这样做:它会休眠。它在睡眠时不做任何事情,包括响应事件。
  • 是的,after() 不会延迟我的按键,所以它可以立即响应,对吧?
  • @Insomnia,是的。
猜你喜欢
  • 2023-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 2015-07-04
  • 2016-03-30
相关资源
最近更新 更多