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

时间:2016-02-26 14:57:00

标签: python multithreading pyqt5

我尝试创建一个GUI,用于显示一个包含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_())

我的问题是我用来监听新帧的lib需要在一个单独的线程中。我创建了一个线程来监听列表的更新。但是每次更改值时,我都无法更新我的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_())

1 个答案:

答案 0 :(得分:0)

您需要告诉模型底层数据已更改,以便它可以更新视图。这可以通过自定义信号完成,如下所示:

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)