更新而QListView从另一个线程(pyqt5)更新Python列表
问题描述:
我尝试创建一个GUI用于显示蟒蛇512个值的列表0/255更新而QListView从另一个线程(pyqt5)更新Python列表
很简单与PyQt的设置一个QListWidget或而QListView显示此种类列表
from sys import argv, exit
from PyQt5.QtWidgets import QListWidgetItem, QListWidget, QApplication
class Universe(QListWidget):
"""This is a class for a DMX Universe of 512 dimmers"""
def __init__(self):
super(Universe, self).__init__()
for i in range(512):
item = QListWidgetItem('dimmer n° '+str(i+1)+' : 0')
self.addItem(item)
if __name__ == "__main__":
app = QApplication(argv)
list_widget = Universe()
list_widget.show()
exit(app.exec_())
我可以创建一个按钮来发送随机值。没有延迟,一切都很好。
from random import randrange
from sys import argv, exit
from PyQt5.QtWidgets import QListWidgetItem, QListWidget, QApplication, QGroupBox, QVBoxLayout, QPushButton
class DisplayGroup(QGroupBox):
"""This is a group of widgets to display"""
def __init__(self):
super(DisplayGroup, self).__init__()
# create a vertical layout
vbox = QVBoxLayout()
# create an universeand and add it to the layout
universe = Universe()
self.universe = universe
vbox.addWidget(universe)
# create a button to make some noise
button = QPushButton('make some noise')
vbox.addWidget(button)
button.released.connect(self.make_some_noise)
# set the layout on the groupbox
vbox.addStretch(1)
self.setLayout(vbox)
def make_some_noise(self):
self.universe.update([randrange(0, 101, 2) for i in range(512)])
class Universe(QListWidget):
"""This is a class for a DMX Universe of 512 dimmers"""
def __init__(self):
super(Universe, self).__init__()
for index in range(512):
item = QListWidgetItem('dimmer n° '+str(index+1)+' : 0')
self.addItem(item)
def update(self, data):
for index, value in enumerate(data):
item = self.item(index)
item.setText('dimmer n° '+str(index+1)+' : '+str(value))
if __name__ == "__main__":
app = QApplication(argv)
group_widget = DisplayGroup()
group_widget.show()
exit(app.exec_())
我的问题是,我用于侦听新帧的库需要在一个单独的线程。我创建一个线程来侦听列表的更新。但是我无法设法在每次更改值时更新我的QListView/QListWidget。 只有当我点击小部件本身时,才会更新小部件。
我尝试了所有在论坛中找到的内容,但无法使其工作。我尝试使用dataChanged.emit的信号,甚至是一个(丑陋的)全局信号。但是我的观点并没有更新价值。
下面是全球丑陋的最新代码。
如果有人能帮助我这一点。
欢呼声!
from random import randrange
from time import sleep
from sys import argv, exit
from PyQt5.QtCore import QThread, QAbstractListModel, Qt, QVariant
from PyQt5.QtWidgets import QListView, QApplication, QGroupBox, QVBoxLayout, QPushButton
universe_1 = [0 for i in range(512)]
class SpecialProcess(QThread):
def __init__(self):
super(SpecialProcess, self).__init__()
self.start()
def run(self):
global universe_1
universe_1 = ([randrange(0, 101, 2) for i in range(512)])
sleep(0.1)
self.run()
class Universe(QAbstractListModel):
def __init__(self, parent=None):
super(Universe, self).__init__(parent)
def rowCount(self, index):
return len(universe_1)
def data(self, index, role=Qt.DisplayRole):
index = index.row()
if role == Qt.DisplayRole:
try:
return universe_1[index]
except IndexError:
return QVariant()
return QVariant()
class Viewer(QGroupBox):
def __init__(self):
super(Viewer, self).__init__()
list_view = QListView()
self.list_view = list_view
# create a vertical layout
vbox = QVBoxLayout()
universe = Universe()
vbox.addWidget(list_view)
# Model and View setup
self.model = Universe(self)
self.list_view.setModel(self.model)
# meke a process running in parallel
my_process = SpecialProcess()
# set the layout on the groupbox
vbox.addStretch(1)
self.setLayout(vbox)
if __name__ == "__main__":
app = QApplication(argv)
group_widget = Viewer()
group_widget.show()
exit(app.exec_())
答
您需要告诉模型基础数据已更改,以便它可以更新视图。这可以用自定义的信号来完成,像这样:
from PyQt5.QtCore import pyqtSignal
universe_1 = [0 for i in range(512)]
class SpecialProcess(QThread):
universeChanged = pyqtSignal()
def __init__(self):
super(SpecialProcess, self).__init__()
self.start()
def run(self):
universe_1[:] = [randrange(0, 101, 2) for i in range(512)]
self.universeChanged.emit()
sleep(0.1)
self.run()
然后连接到模型是这样的:
my_process = SpecialProcess()
my_process.universeChanged.connect(self.model.layoutChanged.emit)