箭头键输入代码在 tkinter 中不起作用 [英] Arrow key input code not working in tkinter

查看:32
本文介绍了箭头键输入代码在 tkinter 中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following is my short script. It is meant to print right left and up when those arrow keys are held, but I don't know why it does not work.

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() 时,问题就开始了.

The issue began when I started using root.after().

推荐答案

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

In python, functions create a new scope. If a variable isn't found within the function's scope, python looks in the outer (module/file) scope for the variable. You add variables into the current scope with assignment. This all means that:

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

为了实际修改外部作用域中的变量,您需要告诉python您想要明确做类似的事情:

In order to actually modify the variable in an outer scope, you need to tell python that you want to do something like that explicitly:

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

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

This works, but it's not considered good practice because you're changing the state of your program. Now the value of right depends on whether you've called a function which is a bit unsettling.

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

A better way to share data between function calls is to use a class. Then methods (functions bound to an instance of the class) can change the state of that single instance, but the rest of your program can continue as if nothing happened.

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!

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

Here's a slightly more "classy" version of your code:

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()

这篇关于箭头键输入代码在 tkinter 中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆