将项目添加到 QListWidget,而不 UI 冻结?
Add items to a QListWidget, without UI freezing?
我在将大量项目添加到 QListWidget 时遇到了一些问题,UI 暂时没有冻结。这是我目前所拥有的:
import sys
from PyQt4 import QtGui, QtCore
class Worker(QtCore.QThread):
def __init__(self):
super(Worker, self).__init__()
def run(self):
for i in range(25000):
self.emit(QtCore.SIGNAL('ping(QString)'), str(i))
class ListDemo(QtGui.QListWidget):
def __init__(self):
super(ListDemo, self).__init__()
def addToList(self, item):
self.insertItem(0, str(item))
#app.processEvents()
class Demo(QtGui.QDialog):
def __init__(self):
super(Demo, self).__init__()
self.setupUI()
def setupUI(self):
self.resize(434, 334)
self.setWindowTitle('Tester')
self.mainlayout = QtGui.QVBoxLayout(self)
self.listwidget = ListDemo()
self.mainlayout.addWidget(self.listwidget)
self.button = QtGui.QPushButton('P O P U L A T E L I S T')
self.mainlayout.addWidget(self.button)
self.button.clicked.connect(self.populate)
def populate(self):
self.listwidget.clear()
self.worker = Worker()
self.connect(self.worker, QtCore.SIGNAL("ping(QString)"), self.listwidget.addToList)
self.worker.start()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
myapp = Demo()
sys.exit(myapp.exec_())
如果我启用 app.processEvents()
,python 会崩溃。如果我将其排除在外,UI 似乎会在更新之前等待线程完成。
我希望 UI 在每次添加项目时更新。有什么办法可以实现吗?
它比 运行 慢,但 UI 会定期刷新并且不会出现挂起。可能有更好的解决方案,但就目前而言,这似乎可以解决问题。
import sys
import time
from PyQt4 import QtGui, QtCore
class Worker(QtCore.QThread):
def __init__(self):
super(Worker, self).__init__()
def run(self):
batch = []
for i in range(25000):
batch.append(str(i))
if len(batch) >= 100: # update UI in batches
time.sleep(0.005) # small time to rest
self.emit(QtCore.SIGNAL('ping(PyQt_PyObject)'), batch)
batch = []
# leftovers
self.emit(QtCore.SIGNAL('ping(PyQt_PyObject)'), batch)
class MyList(QtGui.QListWidget):
def __init__(self):
super(MyList, self).__init__()
self.setUniformItemSizes(True) #reduces overhead in main thread
def addToList(self, batch):
self.insertItems(0, batch[::-1])
class MyWindow(QtGui.QDialog):
def __init__(self):
super(MyWindow, self).__init__()
self.setupUI()
def setupUI(self):
self.resize(434, 334)
self.setWindowTitle('Tester')
self.mainlayout = QtGui.QVBoxLayout(self)
self.listwidget = MyList()
self.mainlayout.addWidget(self.listwidget)
self.button = QtGui.QPushButton('P O P U L A T E L I S T')
self.mainlayout.addWidget(self.button)
self.button.clicked.connect(self.populate)
def populate(self):
self.listwidget.clear()
self.worker = Worker()
self.connect(self.worker, QtCore.SIGNAL("ping(PyQt_PyObject)"), self.listwidget.addToList)
self.worker.start()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
myapp = MyWindow()
sys.exit(myapp.exec_())
我在将大量项目添加到 QListWidget 时遇到了一些问题,UI 暂时没有冻结。这是我目前所拥有的:
import sys
from PyQt4 import QtGui, QtCore
class Worker(QtCore.QThread):
def __init__(self):
super(Worker, self).__init__()
def run(self):
for i in range(25000):
self.emit(QtCore.SIGNAL('ping(QString)'), str(i))
class ListDemo(QtGui.QListWidget):
def __init__(self):
super(ListDemo, self).__init__()
def addToList(self, item):
self.insertItem(0, str(item))
#app.processEvents()
class Demo(QtGui.QDialog):
def __init__(self):
super(Demo, self).__init__()
self.setupUI()
def setupUI(self):
self.resize(434, 334)
self.setWindowTitle('Tester')
self.mainlayout = QtGui.QVBoxLayout(self)
self.listwidget = ListDemo()
self.mainlayout.addWidget(self.listwidget)
self.button = QtGui.QPushButton('P O P U L A T E L I S T')
self.mainlayout.addWidget(self.button)
self.button.clicked.connect(self.populate)
def populate(self):
self.listwidget.clear()
self.worker = Worker()
self.connect(self.worker, QtCore.SIGNAL("ping(QString)"), self.listwidget.addToList)
self.worker.start()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
myapp = Demo()
sys.exit(myapp.exec_())
如果我启用 app.processEvents()
,python 会崩溃。如果我将其排除在外,UI 似乎会在更新之前等待线程完成。
我希望 UI 在每次添加项目时更新。有什么办法可以实现吗?
它比 运行 慢,但 UI 会定期刷新并且不会出现挂起。可能有更好的解决方案,但就目前而言,这似乎可以解决问题。
import sys
import time
from PyQt4 import QtGui, QtCore
class Worker(QtCore.QThread):
def __init__(self):
super(Worker, self).__init__()
def run(self):
batch = []
for i in range(25000):
batch.append(str(i))
if len(batch) >= 100: # update UI in batches
time.sleep(0.005) # small time to rest
self.emit(QtCore.SIGNAL('ping(PyQt_PyObject)'), batch)
batch = []
# leftovers
self.emit(QtCore.SIGNAL('ping(PyQt_PyObject)'), batch)
class MyList(QtGui.QListWidget):
def __init__(self):
super(MyList, self).__init__()
self.setUniformItemSizes(True) #reduces overhead in main thread
def addToList(self, batch):
self.insertItems(0, batch[::-1])
class MyWindow(QtGui.QDialog):
def __init__(self):
super(MyWindow, self).__init__()
self.setupUI()
def setupUI(self):
self.resize(434, 334)
self.setWindowTitle('Tester')
self.mainlayout = QtGui.QVBoxLayout(self)
self.listwidget = MyList()
self.mainlayout.addWidget(self.listwidget)
self.button = QtGui.QPushButton('P O P U L A T E L I S T')
self.mainlayout.addWidget(self.button)
self.button.clicked.connect(self.populate)
def populate(self):
self.listwidget.clear()
self.worker = Worker()
self.connect(self.worker, QtCore.SIGNAL("ping(PyQt_PyObject)"), self.listwidget.addToList)
self.worker.start()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
myapp = MyWindow()
sys.exit(myapp.exec_())