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列表,通过信号槽实现精准更新:
- 给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)
- 在
update_signal_plot方法中,直接通过SignalModel对象标识对应曲线,不存储数据副本,始终从模型读取最新数据。
二、PyQt多模型共享数据的标准方式
核心遵循单一数据源原则:
- 数据仅在SignalModel这类数据模型中存储,视图(包括GraphModel的PlotWidget)只负责展示,不保存冗余数据。
- 用信号槽机制同步变更:数据模型更新时发出信号,关联的视图/模型监听信号并更新自身状态。
- 大量数据集场景下,推荐使用
QAbstractItemModel子类(如QStandardItemModel),利用其内置的批量更新、信号通知机制,更适配复杂数据管理。
三、关于pyqtSignal传递大型数据
- 不推荐直接传递完整的大型数据集,会产生不必要的数据拷贝,影响性能。
- 更优方案:
- 仅传递数据变更的局部信息(如新增索引、修改范围),适合增量更新场景。
- 传递SignalModel对象本身(PyQt中对象传递是引用传递,无拷贝开销),让接收方直接访问模型的
output_data属性获取最新数据。 - 批量更新时采用延迟更新或分块加载,避免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
相关产品推荐
相关产品推荐

