【问题标题】:Arrow key input code not working in tkinter箭头键输入代码在 tkinter 中不起作用
【发布时间】:2015-01-17 09:00:28
【问题描述】:

以下是我的简短脚本。当这些箭头键被按住时,它的目的是打印右左和上,但我不知道为什么它不起作用。

import Tkinter as tk

right = False
left = False
up = False

def keyPressed(event):
    if event.keysym == 'Escape':
        root.destroy()
    if event.keysym == 'Right':
        right = True
    if event.keysym == 'Left':
        left = True
    if event.keysym == 'Up':
        up = True

def keyReleased(event):
    if event.keysym == 'Right':
        right = False
    if event.keysym == 'Left':
        left = False
    if event.keysym == 'Up':
        up = False

def task():
    if right:
        print 'Right'
    if left:
        print 'Left'
    if up:
        print 'Forward'
    root.after(20,task)

root = tk.Tk()
print( "Press arrow key (Escape key to exit):" )

root.bind_all('<Key>', keyPressed)
root.bind_all('<KeyRelease>', keyReleased)
root.after(20,task)

root.withdraw()
root.mainloop()

当我开始使用root.after()时,问题就开始了。

【问题讨论】:

    标签: python tkinter


    【解决方案1】:

    在 python 中,函数创建了一个新的作用域。如果在函数范围内找不到变量,python 会在外部(模块/文件)范围内查找该变量。您可以通过赋值将变量添加到当前范围。这一切都意味着:

    right = False
    def func():
        right = True
    func()
    print (right)  #right is still False in the outer scope.
    

    为了在外部范围内实际修改变量,你需要告诉 python 你想要做类似的事情显式

    right = False
    def func():
        global right
        right = True
    func()
    print (right)
    

    这行得通,但它不被认为是好的做法,因为您正在更改程序的状态。现在right 的值取决于你是否调用了一个有点令人不安的函数。

    在函数调用之间共享数据的更好方法是使用。然后方法(绑定到类实例的函数)可以更改该单个实例的状态,但程序的其余部分可以继续进行,就好像什么都没发生一样。

    class Foo(object):
        def __init__(self):
            self.right = False
        def func(self):
            self.right = True
    
    a = Foo() #calls __init__ implicitly
    print(a.right)  #should be False -- We set this in __init__
    a.func()  #change state of `a`
    print(a.right)  #Now it's True!
    

    这是您的代码稍微“优雅”的版本:

    import Tkinter as tk
    
    class App(object):
        def __init__(self):
            self.right = False
            self.left = False
            self.up = False
    
        def keyPressed(self,event):
            print "HERE"
            if event.keysym == 'Escape':
                root.destroy()
            elif event.keysym == 'Right':
                self.right = True
            elif event.keysym == 'Left':
                self.left = True
            elif event.keysym == 'Up':
                self.up = True
    
        def keyReleased(self,event):
            if event.keysym == 'Right':
                self.right = False
            elif event.keysym == 'Left':
                self.left = False
            elif event.keysym == 'Up':
                self.up = False
    
        def task(self):
            if self.right:
                print 'Right'
            elif self.left:
                print 'Left'
            elif self.up:
                print 'Forward'
            root.after(20,self.task)
    
    application = App()
    root = tk.Tk()
    print( "Press arrow key (Escape key to exit):" )
    
    root.bind_all('<Key>', application.keyPressed)
    root.bind_all('<KeyRelease>', application.keyReleased)
    root.after(20,application.task)
    
    root.mainloop()
    

    【讨论】:

    • 附带说明,我必须删除 root.withdrawl() 以便我仍然有一个窗口可以将键盘命令发送到...
    • 非常感谢,这真的很有帮助:D
    • @SmileyJames -- 没问题。很高兴提供帮助:)
    • 绝对棒极了:D
    猜你喜欢
    • 2020-07-31
    • 1970-01-01
    • 2012-04-11
    • 2015-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多