PyQt4无法从QThread类调用主Gui类的函数

时间:2015-01-29 09:17:17

标签: python pyqt4 qthread

以下是我打算实施更长时间操作的示例代码结构。为了进行更大的操作,我使用了QThread并使用发出的信号更新了进度条(来自主类)。一切正常,直到大量耗时的操作完成。但是,当我从主GUI类调用一个函数时,我遇到了问题。这是我正在尝试的代码结构(阅读评论): -

import time
from scripts.gui import Ui_Dialog
from PyQt4 import QtGui
from PyQt4 import QtCore

class AppGui(QtGui.QDialog, Ui_Dialog):
    def __init__(self):
        QtGui.QDialog.__init__(self)
    # Main code here.
    # This GUI pops up for user input and opens a main GUI.

    def main_function(self):
        # Doing some main coding here.

        self.work_thread = WorkThread()
        self.work_thread.update.connect(self.ui.progressBar.setValue)
        self.work_thread.start()

        # I wanted to continue more coding here after the thread is finished. But self.work_thread.wait() is blocking main gui.
        # Therefore, I moved the continuation code to different function --> sub_function()

    def sub_function(self):

        # Do the remaining code left over from the main_function()


class WorkThread(QtCore.QThread):


    update = QtCore.pyqtSignal(int)

    def __init__(self):
        QtCore.QThread.__init__(self)

    def __del__(self):
        self.wait()

    def run(self):

        self.thread = GenericThread(scripts.function, arg1, arg2)  # This "scripts.function()" function does long process.
        self.thread.start()

        while self.thread.isRunning():
            # Do some long process.
            time.sleep(1)
            self.update.emit(signal)

        print "Distro extraction completed..."


        if self.thread.isFinished():
            self.main_class = AppGui()
            self.main_class.sub_function()  # <-- Problematic call to main AppGui function.

        if self.isFinished():

            return


class GenericThread(QtCore.QThread):

    def __init__(self, function, *args, **kwargs):
        QtCore.QThread.__init__(self)
        self.function = function
        self.args = args
        self.kwargs = kwargs

    def __del__(self):
        self.wait()

    def run(self):
        self.function(*self.args, **self.kwargs)
        return

这是我跑完后得到的。

  

我认为我错误地从WorkThread()类调用主AppGui()函数。

QPixmap: It is not safe to use pixmaps outside the GUI thread
Larger operation is complete...
QObject::installEventFilter(): Cannot filter events for objects in a different thread.
[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python2.7: ../../src/xcb_io.c:179: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.

感谢您解决此问题的任何帮助。

1 个答案:

答案 0 :(得分:1)

原因是工作线程发出信号,此信号无法直接绑定到UI插槽,但您需要将其绑定到常规插槽,然后调用UI插槽进行升级。因为我没有你所有的代码,所以我写了一个这样的类似文件,它工作正常

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import time


class WorkerThread(QThread):
    updateSignal = pyqtSignal(int)

    def run(self):
        count = 0
        while True:
            time.sleep(0.1)
            self.updateSignal.emit(count)
            count += 1


class ProgressBar(QProgressBar):
    def __init__(self, parent=None):
        super(ProgressBar, self).__init__(parent)
        self.worker = WorkerThread()
        self.worker.updateSignal.connect(self.updateProgress) # here should bind to a general slot

    def startWorker(self):
        self.worker.start()

    def updateProgress(self, progress):
        self.setValue(progress)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    p = ProgressBar()
    p.startWorker()
    p.show()
    app.exec_()