Python中的线程结束事件

3 投票
4 回答
2604 浏览
提问于 2025-04-15 11:21

我有一个用PyQt写的程序,在这个程序里,我启动了一个新的线程来绘制一个复杂的图像。现在我想知道这个线程什么时候完成,这样我就可以把图像显示在界面上。

我遇到的唯一问题是,我需要从图形界面的线程里调用绘图的方法,所以我想找个办法让绘图线程告诉图形界面的线程去做某件事。

如果我只用一个线程的话,程序就会卡住。

我以前在C#中用过一个叫BackgroundWorker的东西,它有一个完成事件。

在Python中有没有类似的办法?还是说我应该对PyQt应用的主循环进行一些修改?

4 个回答

0

我觉得你的绘图线程可以通过QApplication.postEvent把一个事件发送到主线程。你只需要选择一个对象作为事件的接收者。更多信息

2

我在一个项目中遇到了类似的问题,使用信号来告诉我的主界面线程什么时候显示工作结果和更新进度条。

需要注意的是,在PyQt参考指南中有很多连接对象和信号的例子。但并不是所有的例子都适用于Python(我花了一段时间才意识到这一点)。

这里有一些你需要查看的例子,用于将Python信号连接到Python函数。

QtCore.QObject.connect(a, QtCore.SIGNAL("PySig"), pyFunction)
a.emit(QtCore.SIGNAL("pySig"), "Hello", "World")

另外,别忘了在你的工作类中添加__pyqtSignals__ = ( "PySig", )

下面是我做的一个简化版本:

class MyGui(QtGui.QMainWindow):

    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        self.worker = None

    def makeWorker(self):
        #create new thread
        self.worker = Worker(work_to_do)
        #connect thread to GUI function
        QtCore.QObject.connect(self.worker, QtCore.SIGNAL('progressUpdated'), self.updateWorkerProgress)
        QtCore.QObject.connect(self.worker, QtCore.SIGNAL('resultsReady'), self.updateResults)
        #start thread
        self.worker.start()

    def updateResults(self):
        results = self.worker.results
        #display results in the GUI

    def updateWorkerProgress(self, msg)
        progress = self.worker.progress
        #update progress bar and display msg in status bar


class Worker(QtCore.QThread):

    __pyqtSignals__ = ( "resultsReady", 
                        "progressUpdated" )

    def __init__(self, work_queue):
        self.progress = 0  
        self.results = []
        self.work_queue = work_queue
        QtCore.QThread.__init__(self, None)

    def run(self):
        #do whatever work
        num_work_items = len(self.work_queue)
        for i, work_item in enumerate(self.work_queue):
            new_progress = int((float(i)/num_work_items)*100)
            #emit signal only if progress has changed
            if self.progress != new_progress:
                self.progress = new_progress
                self.emit(QtCore.SIGNAL("progressUpdated"), 'Working...')
            #process work item and update results
            result = processWorkItem(work_item)
            self.results.append(result)
        self.emit(QtCore.SIGNAL("resultsReady"))
3

在这个示例中,有一个叫做 PyQt-Py2.6-gpl-4.4.4-2.exe 的软件包,其中包含了一个Mandelbrot应用程序。在我安装的版本中,源代码位于 C:\Python26\Lib\site-packages\PyQt4\examples\threads\mandelbrot.pyw。这个程序使用了一个线程来绘制图像,并且通过一个信号(可以在代码中搜索 QtCore.SIGNAL)来通知图形界面的线程该开始绘制了。看起来这正是你想要的功能。

撰写回答