使用从另一个线程更新的 python 列表更新 QlistView (pyqt5)

Update QlistView with python list updated from another thread (pyqt5)

我尝试创建一个 GUI 来显示 python 512 个值的列表 0/255

使用 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)