【问题标题】:Working the function in the background - how? Python and PyQT在后台运行该功能 - 如何? Python 和 PyQT
【发布时间】:2011-12-12 23:47:24
【问题描述】:

我有一个用 Python 编写的相对较大的应用程序,并使用 PyQT 作为 GUI 前端。整个应用程序在一个类中,在一个文件中。

这是一个示例代码:

class Application(QMainWindow):
  def __init__(self):
    super(etc...)

    self.connect(self.mainBtn, SIGNAL("clicked()"), self.do_stuff)

  def do_stuff(self):
    <checking some parameters>
    else:
      do_some_other_long_stuff()


  def do_some_other_long_stuff(self):
     500 lines of code of stuff doing

但是,这就是问题所在:当我单击 mainBtn 时,一切正常,除了 GUI 冻结 - 在执行该功能之前我不能做任何其他事情(而且它是一个网络爬虫,所以它需要相当长的时间一点时间)。当函数 do_some_other_long_stuff 结束时,一切恢复正常。这真的很烦人。

有没有办法以某种方式“背景化” do_some_other_stuff 过程?我查看了 QThreads,它似乎就是这样做的,但这需要我重写所有代码,将我的程序的一半放在不同的类中,因此必须更改所有变量名(从 GUI 获取变量时)课并把它放在工人阶级)

【问题讨论】:

    标签: python pyqt


    【解决方案1】:

    Handling gui with different threads 的副本, How to keep track of thread progress in Python without freezing the PyQt GUI?

    您的 do_stuff() 函数需要启动计算线程然后返回。多线程是在单个进程中运行多个活动的名称 - 根据定义,如果某事“在后台”发生,它会在单独的线程上运行。但是您不需要将函数拆分为不同的类来使用线程,只需确保计算函数不会对 GUI 做任何事情,并且主线程不会调用计算线程使用的任何函数。

    编辑 10/23:这是在单个类中运行线程的愚蠢示例 - 语言或线程库中的任何内容都不需要为每个线程使用不同的类。这些示例可能使用单独的类进行处理,以说明良好的模块化编程。

    from tkinter import *
    import threading
    
    class MyApp:
        def __init__(self, root):
            self.root = root
            self.timer_evt = threading.Event()
            cf = Frame(root, borderwidth=1, relief="raised")
            cf.pack()
            Button(cf, text="Run", command=self.Run).pack(fill=X)
            Button(cf, text="Pause", command=self.Pause).pack(fill=X)
            Button(cf, text="Kill", command=self.Kill).pack(fill=X)
    
        def process_stuff(self):        # processing threads
            while self.go:
                print("Spam... ")
                self.timer_evt.wait()
                self.timer_evt.clear()
    
        def Run(self):                  # start another thread
            self.go = 1
            threading.Thread(target=self.process_stuff, name="_proc").start()
            self.root.after(0, self.tick)
    
        def Pause(self):
            self.go = 0
    
        def Kill(self):                 # wake threads up so they can die
            self.go = 0
            self.timer_evt.set()
    
        def tick(self):
            if self.go:
                self.timer_evt.set()    # unblock processing threads
                self.root.after(1000, self.tick)
    
    def main():
        root = Tk()
        root.title("ProcessingThread")
        app = MyApp(root)
        root.mainloop()
    
    main()
    

    【讨论】:

    • 谢谢。那么如何在不创建不同的 Class() 的情况下使用多个线程呢?我在网上找到的所有示例都使用不同的类。
    • @Deusdies:一个类有 500 行或更多行,你真的不想重构这个巨大的“god-class”吗?
    • @HovercraftFullOfEels:这是最终的解决方案。但如果可能的话,我宁愿不必这样做。
    猜你喜欢
    • 2020-08-06
    • 1970-01-01
    • 2021-04-14
    • 2021-02-26
    • 2013-02-24
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    • 2021-04-16
    相关资源
    最近更新 更多