我有2个QListWidget
列表对象,第一个包含一些数据,然后显示主GUI,第二个是在从第一个列表中选择某些内容时填充另一个数据...我正在尝试使用多线程在第二个列表中填充100万个项目,以便在该任务正在进行时不冻结主GUI窗口。
self.lst1= QtGui.QListWidget(self.groupBox)
self.lst2= QtGui.QListWidget(self.groupBox)
self.lst1.itemSelectionChanged.connect(lambda: self.thread_list_filler(idx = 0))
def thread_list_filler(self, idx):
if idx == 0:
th = Thread(target = self.fill_List2)
th.start()
def fill_List2(self):
self.lst2.clear()
for i in range(1,1000000+1):
self.lst2.addItem(str(i))
每当我按下lst1
中的某个项目时,GUI都会崩溃,问题是什么以及如何避免这种情况?
答案 0 :(得分:1)
你不应该与主线程之外的gui元素进行交互。即您应该在线程中发出一个信号,并将此信号连接到一个插槽,该插槽将执行实际的添加到列表业务。
但请注意,100万个项目是放入QListWidget的大量数据。
无论如何,这样的事情可能有用:
class MyWidget(QtGui.QWidget):
addRequested = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent)
layout = QtGui.QVBoxLayout(self)
self.groupBox = QtGui.QGroupBox('Test', self)
layout.addWidget(self.groupBox)
vlayout = QtGui.QVBoxLayout(self.groupBox)
self.button = QtGui.QPushButton("Fill it", self.groupBox)
self.lst2 = QtGui.QListWidget(self.groupBox)
vlayout.addWidget(self.button)
vlayout.addWidget(self.lst2)
self.button.clicked.connect(self.thread_list_filler)
self.addRequested.connect(self.lst2.addItem)
def thread_list_filler(self):
self.lst2.clear()
th = threading.Thread(target = self.fill_List2)
th.start()
def fill_List2(self):
for i in range(1,1000000+1):
self.addRequested.emit(str(i))
答案 1 :(得分:0)
即使我问了这个问题已经有一段时间了,但这里有一个适合我的问题的解决方案。
from PyQt4 import QtGui, QtCore
from qTest import Ui_Form
import sys
from time import sleep
class WorkerThread(QtCore.QThread):
def __init__(self, parent):
super(WorkerThread, self).__init__(parent)
self.stopFlag = False
def run(self):
for i in xrange(0, 1000000):
if self.stopFlag:
break
self.emit(QtCore.SIGNAL('addIntoList(int)'), i)
sleep(0.001)
self.stopFlag = False
def stop(self):
self.stopFlag = True
class TEST(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.ui.pushButton.clicked.connect(self.stopThread)
self.ui.pushButton_2.clicked.connect(self.close)
self.lst1 = self.ui.listWidget_1
self.lst2 = self.ui.listWidget_2
self.qThread = WorkerThread(self)
self.connect(self.qThread, QtCore.SIGNAL("addIntoList(int)"), self.addIntoList)
for i in range(10):
self.lst1.addItem("%d" % i)
self.lst1.currentRowChanged.connect(self.thread_list_filler)
@QtCore.pyqtSlot(int)
def addIntoList(self, item):
self.lst2.addItem(str(item))
def stopThread(self):
self.qThread.stop()
def thread_list_filler(self, row):
if self.qThread.isRunning():
self.qThread.stop()
self.qThread.wait()
self.lst2.clear()
if row == 0:
self.qThread.start()
QtGui.QApplication.setStyle('cleanlooks')
font = QtGui.QFont()
font.setPointSize(10)
font.setFamily('Arial')
app = QtGui.QApplication(sys.argv)
app.setAttribute(QtCore.Qt.AA_DontShowIconsInMenus,False)
app.setFont(font)
window = TEST()
window.show()
sys.exit(app.exec_())