更新而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)