I'm building a plotting UI that lets a user generate multiple plots from loaded data sets. As part of this the user can add marker lines to their plots to examine (x, y) values by moving those marker lines across the plot.
The functions below work fine if the markers are added to each plot separately (i.e. add_marker to Plot1, Plot2, etc. separately via the elif block of code). However, if the "add to all" option is selected, resulting in the usage of the for loop block of code in the add_marker function all of the markers end up being children of the last plotItem in the list (plot_objects).
If I check the marker objects as the loop iterates when the add_marker function is called the objects, and their parents, are distinct. However, if I check the parents in the update_marker_vals function the parent for markers 1 and 2 are incorrect for all but the last plot in the list.
Not sure what's going on here, but I assume it has something to do with the two sigDragged.connect statements, seeing as everything else seems fine before then.
Code:
def add_marker(self):
name = self.markersPlot_dropdown.currentText()
if name == "All":
for plot_name, plt in self.plot_objects.items():
x_val = (plt.viewRange()[0][0]+plt.viewRange()[0][1])/2
marker_one = plt.addLine(x=x_val*0.5, pen=pg.mkPen('g', width=2.0), movable=True)
marker_two = plt.addLine(x=x_val*1.5, pen=pg.mkPen('c', width=2.0), movable=True)
marker_one.sigDragged.connect(lambda: self.update_marker_vals(marker_one, "Marker One"))
marker_two.sigDragged.connect(lambda: self.update_marker_vals(marker_two, "Marker Two"))
self.plot_markers[plot_name] = {"Marker One": marker_one, "Marker Two:": marker_two}
elif name:
plt = self.plot_objects[name]
x_val = (plt.viewRange()[0][0]+plt.viewRange()[0][1])/2
marker_one = plt.addLine(x=x_val*0.5, pen=pg.mkPen('g', width=2.0), movable=True)
marker_two = plt.addLine(x=x_val*1.5, pen=pg.mkPen('c', width=2.0), movable=True)
marker_one.sigDragged.connect(lambda: self.update_marker_vals(marker_one, "Marker One"))
marker_two.sigDragged.connect(lambda: self.update_marker_vals(marker_two, "Marker Two"))
self.plot_markers[name] = {"Marker One": marker_one, "Marker Two:": marker_two}
def update_marker_vals(self, marker, marker_num):
plot_item = marker.parentItem().parentItem().parentItem()
plot_name = list(self.plot_objects.keys())[list(self.plot_objects.values()).index(plot_item)]
sampling_divisor = self.selected_curve[plot_name].getData()[0][1] -
self.selected_curve[plot_name].getData()[0][0]
index = int(marker.getXPos() / sampling_divisor)
x_val = self.selected_curve[plot_name].getData()[0][index]
y_val = self.selected_curve[plot_name].getData()[1][index]
if marker_num == "Marker One":
print(plot_name)
print("Marker One, :" + str(index))
print(x_val, y_val)
elif marker_num == "Marker Two":
print(plot_name)
print("Marker Two, :" + str(index))
print(x_val, y_val)
Edit:
On a side note, as a solution I can separate this function out into two functions - one function that creates the two markers and then another function that takes the input from the QComboBox and creates one set of markers for a specific plot or creates markers for all the plots available. This works, and is my current solution, but I'm still curious as to what the issue is with the above code.
See Question&Answers more detail:
os