我正在制作一个小程序来计算大学课程的加权成绩。大多数情况下,只是为了尝试使用python tkinter而做。在一个唯一的窗口中,我有四个条目,以及四个标签和四个按钮。这些分别用于获取加权部分的数量,加权部分的名称,权重和获得的积分。底部还有一个第五个按钮,用于计算成绩。
我遇到了一个问题,即多次按下最后一个按钮时,在调用关联的事件处理程序之前会有2或3秒的延迟。我尝试过几种不同的方法来构造程序,并一直遇到相同的问题。现在,我在自己的线程上运行了tkinter mainloop,在另一个线程上运行了所有事件处理。这很奇怪,因为如果我单击tkinter窗口,然后在单击按钮之前将焦点放在其他位置,则通常不会挂起。但是,如果我直接从使用四个条目转到单击按钮,则通常会挂起。如果我完全忽略所有条目,仅单击底部按钮,就永远不会挂任何东西。具体来说,当我单击按钮时,直到2或3秒钟后,按钮的回调才开始执行。
挂起的是generate_report_btn
中定义的view.py
命令。它调用的函数是generate_report
command.py
[我的代码结构类似于在中级文章here中找到的说明。
我在做什么错?
这是我的代码:
if __name__ == "__main__":
root = tk.Tk()
q = Queue()
view_ref = view(root, q)
model = SimpleNamespace(
names_count=0,
weights_count=0,
points_count=0,
number_of_sections=0,
sections={},
)
t = Thread(target=controller, args=(view_ref, model, q,))
t.daemon = True
t.start()
tk.mainloop()
def view(root, q):
root.minsize(900, 700)
root.grid_rowconfigure(0, weight=1)
root.grid_rowconfigure(1, weight=1, minsize=75)
root.grid_columnconfigure(0, weight=1, minsize=400)
root.grid_columnconfigure(1, weight=1)
# Define main window widgets
main_frame = ttk.Frame(root, padding="8 8 8 200")
# (...)
# Generate Report widgets
generate_report_frame = ttk.Frame(root)
generate_report_frame.grid_columnconfigure(0, weight=1)
generate_report_frame.grid_rowconfigure(0, weight=1)
generate_report_btn = ttk.Button(
generate_report_frame,
text="Generate Report",
command=lambda: q.put(controller.Messages.GENERATE_REPORT),
)
# Grid main_frame
main_frame.grid(row=0, column=0, sticky="nsew")
# (...)
# Grid generate report widgets
generate_report_frame.grid(row=1, column=0, sticky="nsew")
generate_report_btn.grid(row=0, column=0, pady=20, sticky="s")
# (...)
return SimpleNamespace(
lbl2_var=lbl2_var,
lbl3_var=lbl3_var,
lbl4_var=lbl4_var,
entry1_var=entry1_var,
entry2_var=entry2_var,
entry3_var=entry3_var,
entry4_var=entry4_var,
btn1=btn1,
entry1=entry1,
btn3=btn3,
entry3=entry3,
btn4=btn4,
entry4=entry4,
btn2=btn2,
entry2=entry2,
)
# (...)
def generate_report():
print("generate_report")
def controller(view_ref, model, q):
while True:
msg = q.get()
if msg == Messages.GET_NUMBER_OF_SECTIONS:
# (...)
elif msg == Messages.GET_SECTION_NAME:
# (...)
elif msg == Messages.GET_SECTION_WEIGHT:
# (...)
elif msg == Messages.GET_SECTION_POINTS:
# (...)
elif msg == Messages.GENERATE_REPORT:
generate_report()
[tkinter
不支持多线程,在某种意义上,与其进行的所有交互以及关联的窗口小部件(即GUI)都必须在同一线程中[[在]内]。