[英]PyQt QThread MultiThreading does not work
I have 2 QListWidget
lists, List2 is being filled when some item has been selected from List1 我有2个
QListWidget
列表,当从List1中选择某些项时,正在填充List2
The problem is that, before filling List2 i have to do alot of tasks which freezes my UI for about 5 seconds which is too annoying, i want to make it fill List2 with QThread but it's not working since before initilizing whole class I'm getting an annoying error 问题是,在填充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
Traceback: # AttributeError: 'NoneType' object has no attribute 'text'
# AttributeError: 'NoneType' object has no attribute 'text'
This accures because self.ui.List1.currentItem().text()
is None
这是因为
self.ui.List1.currentItem().text()
为None
Why this fucntion is being called before triggering itemSelectionChanged
signal? 为什么在触发
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()
Thanks @ekhumoro 谢谢@ekhumoro
Your problem is that simply starting the thread is firing the itemSelectionChanged()
signal (because it is in the run
function), which you have connected to your fill_List2()
function. 您的问题是,简单地启动线程会触发
itemSelectionChanged()
信号(因为它在run
函数中),该信号已连接到fill_List2()
函数。 You need to connect the itemSelectionChanged
event on List1
to a SLOT
that will trigger the thread to do the heavy computation and update List2
. 您需要将
List1
上的itemSelectionChanged
事件连接到一个SLOT
,该事件将触发线程进行大量计算并更新List2
。
I've had to make a number of assumptions about what ui
is and what List1
and List2
are and how they're set up, but here is a working example. 我必须对
ui
是什么以及List1
和List2
是什么以及它们的设置方式做出一些假设,但这是一个有效的示例。 I've replaced the heavy computation in your GenericThread
with a simple 2 second delay. 我已经用2秒的简单延迟替换了
GenericThread
的繁重计算。
If I've misinterpreted / made bad assumptions, please update the question and leave a comment 如果我误解了/做出了错误的假设,请更新问题并发表评论
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_())
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.