2011-10-22 21 views
0

我有一个用Python编写的比较大的应用程序,并且使用PyQT作为GUI前端。整个应用程序在一个类中,在一个文件中。在后台工作 - 如何? Python和PyQT

下面是一个例子代码:

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获取变量时类,并把它在工人阶级)

回答

2

复制的Handling gui with different threadsHow 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() 
+0

谢谢。那么如何在不创建不同的Class()的情况下使用多个线程?我在网上找到的所有例子都使用不同的类。 –

+1

@Deusdies:在单个类中有500行或更多行,你不是真的想要重构这个巨大的[[god-class](http://en.wikipedia.org/wiki/God_object))吗? –

+0

@HovercraftFullOfEels:这是最终的解决方案。但如果可能的话,我宁愿不必那样做。 –