令人难以置信的是,如此基本的知识如何被埋没在如此难以找到的地方。我花了将近一个月的谷歌搜索答案 - 观看视频,阅读文档,书籍等 - 如何停止使用Tkinter的用户输入的while循环。
我的代码循环两次并在我能够提供输入之前离开循环!!!
无论如何,理论值得赞赏,但示例代码将会有更大的帮助。非常非常非常感谢你。
# Python 3.5.1
from tkinter import *
from tkinter import ttk
loop = 0
while loop < 2:
print ('loop')
def user_data():
user_input = data.get()
print (user_input)
lb=ttk.Label(root, text="Enter data")
data=ttk.Entry(root)
bt=ttk.Button(root, text='Ok', command=user_data)
lb.grid(row=0, column=1)
data.grid(row=0, column=2)
bt.grid(row=0, column=3)
loop += 1
print ('left loop')
root.mainloop()
答案 0 :(得分:0)
好的,经过大量讨论后,您似乎并不需要等待任何事情。 GUI处于永久等待事件的状态,因此您不需要添加额外的等待。你需要的只是一个&#34; save&#34;按钮,以及用户输入可变数量值的方法。
要允许用户输入多个值,您可以添加一个添加更多条目小部件的按钮。唯一真正的诀窍是保留一个条目小部件列表,以便您可以在程序中稍后获取值。
以下是说明该技术的工作示例。
注意:这不是我在实际GUI中实际执行此操作的方式,因为它依赖于全局变量。重点是说明动态添加条目小部件的一般原则。
import tkinter as tk
def add_entry():
"""
Add two entries, one for a description, one for an amount,
along with some labels
"""
# create the label and entry widgets
label1 = tk.Label(entry_frame, text="Description:")
label2 = tk.Label(entry_frame, text="Amount:")
entry1 = tk.Entry(entry_frame)
entry2 = tk.Entry(entry_frame)
# lay them out on the screen
column, row = entry_frame.grid_size()
label1.grid(row=row, column=0, sticky="e", pady=2)
entry1.grid(row=row, column=1, sticky="ew", pady=2, padx=4)
label2.grid(row=row, column=2, sticky="e", pady=2)
entry2.grid(row=row, column=3, sticky="ew", pady=2, padx=4)
entry_frame.grid_rowconfigure(row, weight=0)
entry_frame.grid_rowconfigure(row+1, weight=1)
# save the entries, so we can retrieve the values
entries.append((entry1, entry2))
# give focus to the new entry widget
entry1.focus_set()
def save():
# iterate over the entries, printing the values
for description_entry, value_entry in entries:
print("description: %s value: %s" %
(description_entry.get(), value_entry.get()))
# this is our global list of entries
entries = []
# create the main window and buttons
root = tk.Tk()
entry_frame = tk.Frame(root)
button_frame = tk.Frame(root)
entry_frame.pack(side="top", fill="both", expand=True)
button_frame.pack(side="bottom", fill="x")
add_button = tk.Button(button_frame, text="add another entry", command=add_entry)
save_button = tk.Button(button_frame, text="Save", command=save)
add_button.pack(side="left")
save_button.pack(side="right")
# create the first entry
add_entry()
# start the main loop -- this is where the GUI starts waiting,
# and why you don't need to add your own loop.
root.mainloop()
答案 1 :(得分:0)
好吧,我认为这个笑话毕竟在我身上。 :-)我花了三天时间告诉你这不可能轻易完成,结果证明我错了。
我很快就会给你代码,让我解释一下我哪里出错了。在我撰写我的最后一条评论时,我想向您解释的主要问题是,当您在GUI控制台中运行控制台Python程序时,这是两个不同的进程,而GUI的事件循环与如何无关。内部Python程序可以工作。
在GUI应用程序中,它因为只有一个进程而崩溃,并且它的事件循环不能同时运行(响应正常的应用程序事件,如重新绘制窗口或处理点击/按键)并保持阻塞(等待你点击按钮)。如果tkinter允许用户进行额外的事件循环,那么事情就会非常简单。这并不是不合理的:因为tkinter已经为自己的目的构造了一个,它只需要向用户公开该构造函数(或其他一些构造方法)。并且不存在任何GIL问题,因为另一个事件循环只是被阻塞(只有一个实际上正在执行)。
一旦我知道我在搜索什么,就不难找到:你构造一个Tk变量(任何类型的布尔值都适用于这种语义),切换它的值,并在回调中将其切换回来。在此期间,你等待它改变。非常简单。 : - )
我试图尽可能少地更改你的代码,当然,一旦你知道了这个机制,你就可以做得更好。我希望我已经回归了你对tkinter的信念。 : - )
from tkinter import *
from tkinter import ttk
root = Tk()
loop = 0
block = BooleanVar(root, False)
while loop < 2:
print ('loop')
def user_data():
user_input = data.get()
print (user_input)
block.set(False)
lb=ttk.Label(root, text="Enter data")
data=ttk.Entry(root)
bt=ttk.Button(root, text='Ok', command=user_data)
lb.grid(row=0, column=1)
data.grid(row=0, column=2)
bt.grid(row=0, column=3)
block.set(True)
root.wait_variable(block)
loop += 1
print ('left loop')
root.mainloop()