gpt4 book ai didi

python - 如何更新pyqtgraph中的绘图?

转载 作者:行者123 更新时间:2023-12-05 01:09:16 26 4
gpt4 key购买 nike

我正在尝试创建一个使用 PyQt5 和 pyqtgraph 的用户界面。我做了两个复选框,每当我选择它们时,我想绘制代码中可用的两个数据集之一,并且每当我取消选择一个按钮时,我希望它清除相应的曲线。有两个带有文本 A1A2 的复选框,每个复选框都绘制一组数据。

我有两个问题:

1- 如果我选择 A1 它会绘制与 A1 关联的数据,只要我不选择 A2,通过取消选择 A1 我可以清除与 A1 相关的数据。但是,如果我选中 A1 框,然后选中 A2 框,则取消选择 A1 不会清除关联的绘图。在这种情况下,如果我选择绘制随机数据,而不是像 sin 这样的确定性曲线,我会看到通过选择任一按钮都会添加新数据,但无法将其删除。

2- 真正的应用程序有 96 个按钮,每个按钮都应该与一个数据集相关联。我认为我编写代码的方式效率低下,因为我需要为一个按钮和数据集复制相同的代码 96 次。有没有办法将我在下面介绍的玩具代码推广到任意数量的复选框?或者,为每个按钮使用/复制几乎相同的代码是通常且正确的方法吗?

代码是:

from PyQt5 import QtWidgets, uic, QtGui
import matplotlib.pyplot as plt
from matplotlib.widgets import SpanSelector
import numpy as np
import sys
import string
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore

app = QtWidgets.QApplication(sys.argv)

x = np.linspace(0, 3.14, 100)
y1 = np.sin(x)#Data number 1 associated to checkbox A1
y2 = np.cos(x)#Data number 2 associated to checkbox A2

#This function is called whenever the state of checkboxes changes
def todo():
if cbx1.isChecked():
global curve1
curve1 = plot.plot(x, y1, pen = 'r')
else:
try:
plot.removeItem(curve1)
except NameError:
pass
if cbx2.isChecked():
global curve2
curve2 = plot.plot(x, y2, pen = 'y')
else:
try:
plot.removeItem(curve2)
except NameError:
pass
#A widget to hold all of my future widgets
widget_holder = QtGui.QWidget()

#Checkboxes named A1 and A2
cbx1 = QtWidgets.QCheckBox()
cbx1.setText('A1')
cbx1.stateChanged.connect(todo)

cbx2 = QtWidgets.QCheckBox()
cbx2.setText('A2')
cbx2.stateChanged.connect(todo)

#Making a pyqtgraph plot widget
plot = pg.PlotWidget()

#Setting the layout
layout = QtGui.QGridLayout()
widget_holder.setLayout(layout)

#Adding the widgets to the layout
layout.addWidget(cbx1, 0,0)
layout.addWidget(cbx2, 0, 1)
layout.addWidget(plot, 1,0, 3,1)

widget_holder.adjustSize()
widget_holder.show()

sys.exit(app.exec_())



最佳答案

下面是我做的一个很好的例子。可以重复使用做更多的绘图而不增加代码,只需要改变self.num的值并使用函数add_data(x,y,ind)添加相应的数据>,其中 xy 是数据的值,ind 是框的索引(从 0n-1)。

import sys
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui

class MyApp(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.central_layout = QtGui.QVBoxLayout()
self.plot_boxes_layout = QtGui.QHBoxLayout()
self.boxes_layout = QtGui.QVBoxLayout()
self.setLayout(self.central_layout)

# Lets create some widgets inside
self.label = QtGui.QLabel('Plots and Checkbox bellow:')

# Here is the plot widget from pyqtgraph
self.plot_widget = pg.PlotWidget()

# Now the Check Boxes (lets make 3 of them)
self.num = 6
self.check_boxes = [QtGui.QCheckBox(f"Box {i+1}") for i in range(self.num)]

# Here will be the data of the plot
self.plot_data = [None for _ in range(self.num)]

# Now we build the entire GUI
self.central_layout.addWidget(self.label)
self.central_layout.addLayout(self.plot_boxes_layout)
self.plot_boxes_layout.addWidget(self.plot_widget)
self.plot_boxes_layout.addLayout(self.boxes_layout)
for i in range(self.num):
self.boxes_layout.addWidget(self.check_boxes[i])
# This will conect each box to the same action
self.check_boxes[i].stateChanged.connect(self.box_changed)

# For optimization let's create a list with the states of the boxes
self.state = [False for _ in range(self.num)]

# Make a list to save the data of each box
self.box_data = [[[0], [0]] for _ in range(self.num)]
x = np.linspace(0, 3.14, 100)
self.add_data(x, np.sin(x), 0)
self.add_data(x, np.cos(x), 1)
self.add_data(x, np.sin(x)+np.cos(x), 2)
self.add_data(x, np.sin(x)**2, 3)
self.add_data(x, np.cos(x)**2, 4)
self.add_data(x, x*0.2, 5)


def add_data(self, x, y, ind):
self.box_data[ind] = [x, y]
if self.plot_data[ind] is not None:
self.plot_data[ind].setData(x, y)

def box_changed(self):
for i in range(self.num):
if self.check_boxes[i].isChecked() != self.state[i]:
self.state[i] = self.check_boxes[i].isChecked()
if self.state[i]:
if self.plot_data[i] is not None:
self.plot_widget.addItem(self.plot_data[i])
else:
self.plot_data[i] = self.plot_widget.plot(*self.box_data[i])
else:
self.plot_widget.removeItem(self.plot_data[i])
break

if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())

请注意,在 PlotWidget 内部,我使用 plot() 方法添加绘图,它返回一个保存在列表中的 PlotDataItem在调用 self.plot_data 之前创建。有了这个,您可以轻松地将其从 Plot Widget 中删除并重新添加。此外,如果您的目标是一个更复杂的程序,例如,您可以在运行时更改每个框的数据,如果您使用 setData() 方法,该图将更新而不会出现重大问题在 PlotDataItem

正如我一开始所说,这应该适用于很多复选框,因为当复选框被选中/未选中时调用的函数,首先将每个框的实际状态与前一个进行比较(存储在 self.state) 并且只对与该特定框相对应的图进行更改。这样,您就可以避免为每个复选框执行一个功能,并在每次选中/取消选中一个框时重新绘制所有 de 框(如 user8408080 所做的)。我不是说它不好,但是如果你增加复选框的数量和/或数据的复杂性,重新绘制所有数据的工作量会急剧增加。

唯一的问题是当窗口太小而无法支持大量复选框(例如 96 个)时,您将不得不在另一个小部件而不是布局中组织复选框。

现在是上面代码的一些截图: enter image description here

然后将 self.num 的值改为 6 并向其中添加一些随机数据:

self.add_data(x, np.sin(x)**2, 3)
self.add_data(x, np.cos(x)**2, 4)
self.add_data(x, x*0.2, 5)

enter image description here

关于python - 如何更新pyqtgraph中的绘图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65395378/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com