以下是我打算实施更长时间操作的示例代码结构。为了进行更大的操作,我使用了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.
感谢您解决此问题的任何帮助。
答案 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_()