Python3,了解tkinter-mainloop()或QtPy-exec _()

时间:2016-04-15 18:08:13

标签: python qt tkinter python-3.5

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()

1 个答案:

答案 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如何设计工作的。如果您有长时间运行的计算,则应将这些计算放在单独的线程或进程中。