You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5 GUI多模型间数据共享方案及性能疑问

引言

您好,我正在开发一个交互式GUI,用于在多个图表上显示多组数据集。
设计思路是可以添加、删除数据集和图表,并且能够选择在哪个图表上显示哪个数据集,甚至可以将一个数据集显示在多个图表上……

![GUI]

在MainModel中,我创建和删除SignalModel(用于存储和处理数据集)与GraphModel,并将它们分别存储在graphs和signals列表中,代码如下所示。

MainModel代码

class MainModel(QObject):
  # signals
  
  @property
  def signals(self):
    return self._signals

  def signals_append(self, value: SignalModel):
    value.on_delete.connect(self.signals_delete)
    self._signals.append(value)

  def signals_delete(self, value: SignalModel):
    self._signals.remove(value)

  @property
  def graphs(self):
    return self._graphs

  def graphs_append(self, value: GraphModel):
    value.on_delete.connect(self.graphs_delete)
    self._graphs.append(value)

  def graphs_delete(self, value: GraphModel):
    print("Deleting: ", str(value))
    self._graphs.remove(value)
    value.deleteLater()
    print(self._graphs)

  def __init__(self):
    super().__init__()

    self._signals = []
    self._graphs = []

SignalModel代码

class SignalBarModel(QObject):

  @property
  def name(self):
    return self._name

  @name.setter
  def name(self, value: str):
    self._name = value
    self.on_name_changed.emit(value)

  @property
  def color(self):
    return self._color

  @color.setter
  def color(self, value):
    self._color = value
    self.on_color_changed.emit(value)

  @property
  def input_data(self):
    return self._input_data

  @input_data.setter
  def input_data(self, value: list):
    self._input_data = value
    # call function for calculating output_data

  @property
  def output_data(self):
    return self._output_data

  @output_data.setter
  def output_data(self, value):
    self._output_data = value
    self.on_output_data_changed.emit(value)

  def __init__(self):
    super().__init__()

    self._name = "Signal"
    self._color = "WHITE"

    self._input_data = []

    self._output_data = []
问题

我不确定在GraphModel中传递和存储数据的最佳方式,因为它可能来自一个、两个甚至数百个SignalModel,且这些SignalModel可能在程序运行期间被添加或删除。

GraphModel代码

class GraphModel(QObject):
  # Signals

  @property
  def name(self):
    return self._name

  @name.setter
  def name(self, value: str):
    self._name = value
    self.on_name_changed.emit(value)

  @property
  def plot(self):
    return self._plot

  def __init__(self):
    super().__init__()

    self._name = "Graph"
    self._plot = PlotWidget()

    # Data points from multiple signals or SignalModel??
    self._data = []
    self._signals = []  # SignalModel

  def delete(self):
    self.on_delete.emit(self)
    self.on_delete_views.emit()

我曾尝试将SignalModel的pyqtSignal连接到GraphModel以更新数据,但这样需要知晓其他SignalModel的数据集。我尝试让一个SignalModel数据变化时所有SignalModel都发送pyqtSignal,结果造成了混乱。

之后我想到两种解决方案,但还未测试,希望先获取更多意见:

  • 为SignalModel添加ID,记录GraphModel关联的ID,并将捕获的数据存储到对应ID下。(我不太想这么做,但必要时会采用)
  • 每次数据变化或断开图表与信号的连接时,发送携带SignalModel的pyqtSignal。但不确定单个信号包含大量数据点时的性能影响。

由于我对GUI设计和PyQt5了解不深,可能忽略了更高效的方案,希望得到您的建议。

疑问
  • PyQt5中多模型间共享数据的标准方式是什么?
  • 是否推荐通过pyqtSignal传递大型数据类(完整模型)?

解决方案建议

一、GraphModel与SignalModel的关联优化

不用额外添加ID,直接让GraphModel维护关联的SignalModel列表,通过信号槽实现精准更新:

  1. 给GraphModel添加关联管理方法:
def add_signal(self, signal_model: SignalBarModel):
    if signal_model not in self._signals:
        self._signals.append(signal_model)
        # 连接数据变更信号,绑定到对应更新逻辑
        signal_model.on_output_data_changed.connect(lambda data: self.update_signal_plot(signal_model, data))
        signal_model.on_color_changed.connect(lambda color: self.update_signal_color(signal_model, color))
        signal_model.on_delete.connect(lambda: self.remove_signal(signal_model))
        # 初始化渲染当前数据
        self.update_signal_plot(signal_model, signal_model.output_data)

def remove_signal(self, signal_model: SignalBarModel):
    if signal_model in self._signals:
        # 断开所有信号连接
        signal_model.on_output_data_changed.disconnect()
        signal_model.on_color_changed.disconnect()
        signal_model.on_delete.disconnect()
        self._signals.remove(signal_model)
        # 从图表中移除该信号的曲线
        self.clear_signal_plot(signal_model)
  1. 在update_signal_plot方法中,直接通过SignalModel对象标识对应曲线,不存储数据副本,始终从模型读取最新数据。

二、PyQt多模型共享数据的标准方式

核心遵循单一数据源原则:

  • 数据仅在SignalModel这类数据模型中存储,视图(包括GraphModel的PlotWidget)只负责展示,不保存冗余数据。
  • 用信号槽机制同步变更:数据模型更新时发出信号,关联的视图/模型监听信号并更新自身状态。
  • 大量数据集场景下,推荐使用QAbstractItemModel子类(如QStandardItemModel),利用其内置的批量更新、信号通知机制,更适配复杂数据管理。

三、关于pyqtSignal传递大型数据

  • 不推荐直接传递完整的大型数据集,会产生不必要的数据拷贝,影响性能。
  • 更优方案:
    1. 仅传递数据变更的局部信息(如新增索引、修改范围),适合增量更新场景。
    2. 传递SignalModel对象本身(PyQt中对象传递是引用传递,无拷贝开销),让接收方直接访问模型的output_data属性获取最新数据。
    3. 批量更新时采用延迟更新或分块加载,避免GUI卡顿。

额外优化

给SignalModel添加删除信号,确保模型被删除时自动通知所有关联GraphModel清理:

# 在SignalBarModel的__init__中添加
self.on_delete = pyqtSignal(SignalBarModel)

# 新增删除方法
def delete(self):
    self.on_delete.emit(self)

在MainModel的signals_delete中调用signal_model.delete(),实现自动清理关联。


内容的提问来源于stack exchange,提问作者ves_el

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 22:14:53