【发布时间】:2018-06-22 22:21:45
【问题描述】:
我在向 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 似乎会在更新之前等待线程完成。
我希望用户界面在每次添加项目时更新。有什么方法可以实现吗?
【问题讨论】:
-
在这种情况下使用线程不会阻止 gui 冻结。事实上,即使它起作用了,它也可能会让事情变得更慢。根本无法在一个步骤中 有效地将大量项目添加到列表小部件。您需要采取完全不同的方法。最常见的解决方案之一是在滚动列表小部件时分批填充列表。另一种是将列表视图与自定义模型一起使用。 (见here)。
-
感谢@ekhumoro 的链接。自定义模型似乎绝对是最有效的方法,但要明确的是,我不想一步添加项目。我的示例是我正在处理的更大脚本的一个极其简化的版本,我正在填充的列表可能需要一些时间来填充,所以我希望在填充时绘制每个项目,给人的印象用户界面正在运行,而不是冻结。
-
在这种情况下,您的问题完全不清楚且具有误导性。第一句话是指“向 QListWidget 添加大量项目”,代码示例正试图做到这一点。我建议您根据您的实际需求重新编写问题并提供更相关的代码示例。
-
我仍在尝试将大量项目添加到 QListWidget - 或 QListView... 我只是不想一步完成。我认为我的结束语基本上涵盖了这一点。到目前为止,我的示例与我想要实现的目标相去甚远吗?
-
你现在只是在玩语义游戏。显然,无论您采用哪种方法,都必须逐个添加项目。这是每个批次中添加了多少项目的问题(正如我在第一条评论中已经建议的那样)。您当前的代码尝试转储 25000 个项目的连续流 - 更糟糕的是,它还尝试强制单独的 gui 更新为这些项目中的每一项。工作线程实际上并没有做任何有用的事情,所有耗时的工作仍在主线程内完成(只是以一种极其低效的方式)。