下面是我制作的一个示例,效果很好。
可以重复使用做更多的绘图,无需增加代码,只需更改self.num
并使用函数添加相应的数据add_data(x,y,ind)
, where x
and y
是数据的值,ind
是盒子的索引(来自0
to n-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 框(例如用户8408080 https://stackoverflow.com/users/8408080/user8408080做过)。我并不是说这不好,但如果增加复选框的数量和/或数据的复杂性,重新绘制所有数据的工作量将急剧增加。
唯一的问题是,当窗口太小而无法支持大量复选框(例如 96 个)时,您将不得不在另一个小部件而不是布局中组织复选框。
Now some screenshots of the code from above:
然后改变值self.num
to 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)