【问题标题】:Python main script not waiting for user response in Tkinter GUIPython 主脚本不等待 Tkinter GUI 中的用户响应
【发布时间】:2020-07-04 17:48:32
【问题描述】:

我是使用 Tkinter GUI 的新手,在尝试制作交互式程序时卡住了 1) 在 GUI 中征求用户的反馈,2) 等待用户响应并按 Enter,3) 然后使用输入以通知主脚本中的后续步骤。

但是,我无法正确执行第 2 步。在函数调用 waitforinput() 中,我希望主脚本在继续执行测试打印输出的下一行之前等待。相反,它使用 '' 作为结果打印主脚本测试行,然后放置一个有效的输入框。为什么这个程序在waitforinput函数完成之前就移动到下一行?谢谢!

import tkinter as tk
from tkinter import *
import threading, time

# assignments for input thread
WAIT_DELAY = 250 #milliseconds
lock = threading.Lock()  # Lock for shared resources.
finished = False
result = ''

# Set up the graphical interface
root = tk.Tk(className='My Flashcards')

def main():    
    # request and wait for input from user 
    waitforinput()
    Test = tk.Label(root, text = "result = " + result)
    Test.pack()
    Test.config(font = ('verdana', 24), bg ='#BE9CCA')

# sets background thread for getinput from user
def waitforinput():
    global finished
    with lock:
        finished = False
    t = threading.Thread(target=getinput)
    t.daemon = True
    root.after(WAIT_DELAY, check_status) # start waiting
    t.start()

# checks to see if user has inputted
def check_status():
    with lock:
        if not finished: 
            root.after(WAIT_DELAY, check_status) # keep waiting

# solicits and returns a string from the user
def getinput():
    
    # declaring string variable for storing name and password 
    answer_var = tk.StringVar()
        
    # define a function that will get the answer and return it
    def user_response(event = None):
        answer = answer_entry.get()
        global result
        result = answer
        global finished 
        finished = True # to break out of loop
    
    # creating an entry for inputting answer using widget Entry
    answer_entry = tk.Entry(root, width = 1, borderwidth = 5, bg ='#BE9CCA', textvariable = answer_var) ## could be global with args
    
    # making it so that enter calls function
    answer_entry.bind('<Return>', user_response)   

    # placing the entry 
    answer_entry.pack()
    answer_entry.focus()

main()
root.mainloop()
''' 

【问题讨论】:

    标签: python multithreading tkinter


    【解决方案1】:

    您不需要使用线程来等待响应。 Tkinter 有专门用于等待的方法:wait_windowwait_variable

    wait_window 等待窗口被销毁。这通常在创建模式对话框时使用。 wait_variable 可用于等待特殊 tkinter 变量对象之一被修改。

    如果您希望您的代码等到用户在条目中按下回车键,您可以在该键上设置一个绑定以设置一个变量,然后等待该变量被设置。注意:您通常不希望将 wait_variable 用于用作 textvariable 值的变量,因为输入单个字符后等待将停止。

    您的getinput 函数可能看起来像这样,可以不使用线程直接调用:

    def getinput():
    
        answer_var = tk.StringVar()
        def user_response(event):
            answer_var.set(answer_entry.get())
            return
    
        answer_entry = tk.Entry(root, width = 1, borderwidth = 5, bg ='#BE9CCA')
        answer_entry.bind('<Return>', user_response)
        answer_entry.pack()
        answer_entry.focus()
    
        answer_entry.wait_variable(answer_var)
        return answer_var.get()
    

    一旦语句answer_entry.wait_variable(answer_var) 执行,tkinter 将进入一个事件循环并且在设置answer_var 之前不会返回。然后您可以在变量上调用get 并返回值。

    以下是修改main 函数以调用此函数的方法:

    def main():
        result = getinput()
        Test = tk.Label(root, text = "result = " + result)
        Test.pack()
        Test.config(font = ('verdana', 24), bg ='#BE9CCA')
    

    【讨论】:

    • 这太棒了——我离成功又近了一步。但是,就像您提到的那样,当我输入第一个字母时它正在返回,而不是等待输入。有解决办法吗?等待进入的方法?
    • @DavidGallagher:我在回答中解决了这个问题。
    • 你是对的。当我将您的代码复制进去时,一切正常。我有一个分屏模式,没有看到(因此没有删除)文本变量部分。我的错。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多