3个子问题:
[1] python GUI是基于轮询的吗?
在我看来,tk和qtpy都是基于轮询的,如果gui调用一个需要一段时间才能执行的函数,整个gui会挂起。
我很久以前就学会了gui,我记得现代的gui应该是基于中断的,即使gui执行的东西很大,gui应该始终保持响应。 gui可能无法显示那些大计算的结果,但它会响应调整大小,显示按钮点击动画等。所以我的问题是,是否有一个选项如:
#psuedo code
root=tkinter.Tk()
root.setInterruptMode(True)
[2] tk.mainloop()只是一个巨大的循环吗?
如果我的第一个问题是管道梦想,我将只需要了解线程和多进程,那么我的下一个问题是关于root.mainloop()
(或qtpy的exec_()
)。
我的印象是mainloop()并没有真正启动线程或python中的任何东西,它只是将一个巨大且不可见的tkinter的gui轮询+绘制循环打包到我的主线。我的印象是否正确?
[3]为什么将mainloop放入主线?
mainloop()
必须驻留在主线上吗?我可以将其进行线程/多处理吗?这样我的主线可以专注于大型计算,主线可以控制gui进程和IO进程。我遇到的所有示例在主线上都有mainloop()
,我不确定这是推荐的方法还是有什么好处。
下面是我在尝试学习python gui时编写的代码:
import tkinter
import random
class myGUI():
def __init__(self, arg_tkroot):
self.GUI_display = tkinter.Label(arg_tkroot, text='init-ed')
self.GUI_button = tkinter.Button(arg_tkroot, text='click')
self.GUI_display.pack()
self.GUI_button.pack()
self.GUI_button.bind('<Button-1>', self.handle_user_interaction)
self.list_bigData = []
#handles GUI interaction, and call bigData_and_bigCalculation()
def handle_user_interaction(self, arg_event):
print(arg_event, ' detected by myGUI')
strResult_toFeedbackToUser = self.bigData_and_bigCalculation()
self.GUI_display.config(text=strResult_toFeedbackToUser)
print('finished handling user interact')
# slow calculations and memory consuming operations
def bigData_and_bigCalculation(self):
self.list_bigData[:]=[]
for i in range(500000):
self.list_bigData.append( ''.join(random.choice('asdfas') for k in range(10)) )
return self.list_bigData[-1]
# Main()
if __name__ == '__main__':
root = tkinter.Tk()
mygui = myGUI(root)
root.mainloop()
答案 0 :(得分:1)
[1] GUI基于轮询?
GUI是基于事件的 - GUI中发生的所有事情都是对事件的响应。应用程序如何处理事件取决于应用程序。如果事件的处理可以在几百毫秒或更短的时间内发生,则可以在主线程中处理。如果需要更长的时间,应用程序应该在单独的线程或进程中运行代码。
对于Tkinter,Tkinter设计为在单个线程中运行。这并不意味着你不能使用线程,只是对tkinter对象的所有访问都应该在一个线程上。执行此操作的常用方法是让其他线程通过线程安全队列与GUI通信,GUI线程负责定期检查该队列。
所以我的问题是,是否有像{
这样的选项root.setInterruptMode(True)
]
在tkinter中,不,没有办法进入特殊的“中断”模式。
[2]这只是一个巨大的循环?
我假设“它”是指对mainloop
的调用。是的,这是一个巨大的循环。或许更准确地说,这是一个很小的循环。它只是等待事件,然后查找事件的处理程序并运行处理程序。
我的印象是mainloop()并没有真正启动线程或python中的任何东西
正确。它在当前线程中运行事件循环。
[3]为什么将mainloop放入主线?
您必须向原始开发人员询问。可能是因为这对于非常非常大比例的应用程序来说是必要的(当工具箱发明时,可能比现在更真实)。
Tkinter只是一个tcl解释器的包装器,在解释器中加载了tk工具包。 tcl / tk被设计为嵌入在其他应用程序中,因此它需要是轻量级的,并且能够在不支持线程的系统上运行(tcl足够大,不能保证每个平台上的线程支持)
mainloop()必须驻留在主线上吗?我可以将其进行线程/多处理吗?
mainloop()
需要在创建根窗口的同一个线程中运行。如果你需要线程(再次,你很可能不需要),你当然可以在一个单独的线程中运行你的事件处理程序。它增加了复杂性,但如果你需要它就会存在。对于大类程序,根本不需要那么多的复杂性。
您应该能够创建工作线程并从那里创建和运行GUI。我从来没有尝试过,但我认为没有理由说它不起作用。 Tkinter并不关心它是主线程,只是所有tkinter代码都在同一个线程中运行。
我遇到的所有示例都在主线上有mainloop(),我不确定这是推荐的方法还是有什么好处。
在主线程中调用mainloop
是tkinter如何设计工作的。如果您有长时间运行的计算,则应将这些计算放在单独的线程或进程中。