簡體   English   中英

PyQt QThread多線程不起作用

[英]PyQt QThread MultiThreading does not work

我有2個QListWidget列表,當從List1中選擇某些項時,正在填充List2 QListWidgets

問題是,在填充List2之前,我必須執行很多任務,這會使UI凍結約5秒鍾,這太煩人了,我想讓它用QThread填充List2,但由於在初始化整個類之前我無法使用它一個煩人的錯誤

from ui import Ui_Win
from PyQt4 import QtGui, QtCore

class GenericThread(QtCore.QThread):
    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)

    def __del__(self):
        self.quit()
        self.wait()

    def run(self):
        self.emit( QtCore.SIGNAL('itemSelectionChanged()'))
        return

class MainUI(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_Win()
        self.ui.setupUi(self)
        ...

        genericThread = GenericThread(self)
        self.connect(genericThread, QtCore.SIGNAL("itemSelectionChanged()"), self.fill_List2 )
        genericThread.start()

    def fill_List2(self):
        self.ui.List2.clear()
        list1SelectedItem = str(self.ui.List1.currentItem().text()) # ERROR HERE

# AttributeError: 'NoneType' object has no attribute 'text'

這是因為self.ui.List1.currentItem().text()None

為什么在觸發itemSelectionChanged信號之前調用此功能?

from ui import Ui_Win ## ui.py is a file that has been generated from Qt Designer and it contains main GUI objects like QListWidget
from PyQt4 import QtGui, QtCore

class GenericThread(QtCore.QThread):
    def __init__(self, parent=None, listIndex=0):
        QtCore.QThread.__init__(self, parent)
        self.listIndex = listIndex

    def __del__(self):
        self.quit()
        self.wait()

    def run(self):
        if self.listIndex == 2:
            for addStr in Something:
                #Some long stuff
                self.emit( QtCore.SIGNAL('fillListWithItems(QString, int'), addStr, self.listIndex)

class MainUI(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_Win()
        self.ui.setupUi(self)
        ...

        self.ui.List1.list1SelectedItem.connect(self.fill_List2)

    @QtCore.pyqtSlot(QString, int)
    def self.fillListWithItems(addStr, lstIdx):
        if lstIdx==2:
            self.ui.List2.addItem(addStr)

    def fill_List2(self):
        self.ui.List2.clear()
        list1SelectedItem = str(self.ui.List1.currentItem().text())

        genericThread = GenericThread(self, listIndex=2)
        self.connect(genericThread, QtCore.SIGNAL("fillListWithItems(QString, int)"), self.fillListWithItems )
        genericThread.start()

謝謝@ekhumoro

您的問題是,簡單地啟動線程會觸發itemSelectionChanged()信號(因為它在run函數中),該信號已連接到fill_List2()函數。 您需要將List1上的itemSelectionChanged事件連接到一個SLOT ,該事件將觸發線程進行大量計算並更新List2

我必須對ui是什么以及List1List2是什么以及它們的設置方式做出一些假設,但這是一個有效的示例。 我已經用2秒的簡單延遲替換了GenericThread的繁重計算。

如果我誤解了/做出了錯誤的假設,請更新問題並發表評論

test_slotting.py

from ui import Ui_Win
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import pyqtSlot
from PyQt4.QtGui import *
import time

class GenericThread(QtCore.QThread):
    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)

    def __del__(self):
        self.quit()
        self.wait()

    def run(self):
        #Do all your heavy processing here
        #I'll just wait for 2 seconds
        time.sleep(2)
        self.emit( QtCore.SIGNAL('itemSelectionChanged()'))
        return

class MainUI(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_Win()
        self.ui.setupUi(self)
        self.ui.List1 = QListWidget(self)
        self.ui.List2 = QListWidget(self)

        hbox = QtGui.QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(self.ui.List1)
        hbox.addWidget(self.ui.List2)

        self.ui.centralWidget.setLayout(hbox)

        self.ui.List1.addItems(['alpha','beta','gamma','delta','epsilon'])
        self.ui.List2.addItems(['Item1','Item2'])

        self.ui.List1.itemSelectionChanged.connect(self.start_heavy_processing_thread)

    @pyqtSlot()
    def start_heavy_processing_thread(self):
        genericThread = GenericThread(self)
        self.connect(genericThread, QtCore.SIGNAL("itemSelectionChanged()"), self.fill_List2 )
        genericThread.start()

    def fill_List2(self):
        self.ui.List2.clear()
        list1SelectedItem = str(self.ui.List1.currentItem().text())
        self.ui.List2.addItem(list1SelectedItem)

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindow = MainUI()
    MainWindow.show()
    sys.exit(app.exec_())

ui.py

from PyQt4 import QtCore, QtGui

class Ui_Win(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(416, 292)
        self.centralWidget = QtGui.QWidget(MainWindow)
        self.centralWidget.setObjectName("centralWidget")
        MainWindow.setCentralWidget(self.centralWidget)

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindow = QtGui.QMainWindow()
    ui = Ui_Win()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM