我的代码如下:
from tkinter import *
window = Tk()
print("What is 5 times 5?")
optionA = 25
optionB = 10
optionC = 3125
optionD = 55
print("A:", optionA)
print("B:", optionB)
print("C:", optionC)
print("D:", optionD)
def chooseA():
userAnswer = optionA
def chooseB():
userAnswer = optionB
def chooseC():
userAnswer = optionC
def chooseD():
userAnswer = optionD
window.bind("<Left>", chooseA)
window.bind("<Up>", chooseB)
window.bind("<Down>", chooseC)
window.bind("<Right>", chooseD)
if userAnswer == 25:
print("You correctly answered the question!")
我的问题是我收到一条错误消息,提示未定义userAnswer。这是因为该代码没有等待用户按下四个箭头键之一的功能。是否有人对如何使程序等待4个按键中的1个有建议?非常感谢您的回答! (PS。从键盘模块使用keyboard.wait命令不会等待多个键。)
答案 0 :(得分:1)
这是一个解决方案,但也许不是最好的解决方案(可能有一些模块专门用于此目的,但我想尽可能地练习使用线程进行编码)。
from threading import Thread
from tkinter import *
def check_with_thread(): # make a function our thread can attach to
global userAnswer
local_check = userAnswer
while True:
if userAnswer != local_check: # user has selected a new value
if userAnswer == 25:
print("That's correct!")
break # have our thread break infinite loop and end it's execution
else:
print(userAnswer)
local_check = userAnswer # Make it able to detect changes in values
window = Tk() # Actually make a window! Why is this not in the OP???
print("What is 5 times 5?")
optionA = 25
optionB = 10
optionC = 3125
optionD = 55
print("A:", optionA)
print("B:", optionB)
print("C:", optionC)
print("D:", optionD)
def chooseA(event):
global userAnswer # we are modifying the global variable our thread is looking at
userAnswer = optionA
def chooseB(event):
global userAnswer
userAnswer = optionB
def chooseC(event): # the .bind() sends events, so these need a positional argument for them
global userAnswer
userAnswer = optionC
def chooseD(event):
global userAnswer
userAnswer = optionD
window.bind("<Left>", chooseA)
window.bind("<Up>", chooseB)
window.bind("<Down>", chooseC)
window.bind("<Right>", chooseD)
userAnswer = None
t = Thread(target=check_with_thread) # make a thread to check the input
t.start() # get our thread running before generating the window
window.mainloop()
首先,我们为线程定义了一个要执行的函数(线程是您的程序能够立即执行两件事的方法之一。之所以需要这样做是因为window.mainloop()
会阻塞脚本的主线程不做任何其他事情)。我们指定函数需要使用userAnswer
读取全局变量global userAnswer
,否则将期望该变量是局部变量(在函数内定义,并且在函数结束时被忘记,除非返回该变量)。然后,我们将局部变量local_check
初始化为调用函数时碰巧发生的userAnswer
。最后,我们进入无限循环。在此循环中,我们将通过与以前创建的local_check
进行比较来检查用户是否已更新答案。如果答案已更新,则这些值将有所不同!我们将继续检查新的答案,直到他们选择25的正确答案为止,在此我们将调用break
以结束我们的while
循环(否则它将永远持续下去)。至此,我们已经到达函数的末尾,因此分配给它的线程将在此点消失。接下来,我们将创建userAnswers
并为其分配一个值None
,以便当我们的线程到达行local_check = userAnswer
时它将知道该怎么做,并且不会遇到NameError。现在剩下的就是创建线程了。我们使用t = Thread(target=check_with_thread)
进行操作,然后立即启动它。线程现在启动,并检查输入是否更改,我们终于可以在脚本的主线程中启动window.mainloop()
。
使用线程是因为window.mainloop()
正在阻塞。这意味着如果我们尝试过:
# stuff from previous script
window.mainloop()
thing = 5
print(thing)
直到用户关闭后,我们才会看到打印的任何内容。这意味着我们的绑定不再有效,并且不能用于更改用户选择的内容。通过使用线程,我们可以有两个无限循环同时同时处理信息,这对于程序员来说是一个非常有价值的窍门(为什么我会尽可能地练习)
答案 1 :(得分:0)
尝试添加:
window = tkinter.Tk()
位于代码顶部,然后
window.mainloop()
最后。这将创建一个窗口,该窗口将保持打开状态,直到您手动将其关闭。