(self, x_col, y_col)
| 217 | return h |
| 218 | |
| 219 | def draw_plot(self, x_col, y_col): |
| 220 | self.ax.clear() |
| 221 | |
| 222 | plotted = [] # list of (label, line) |
| 223 | |
| 224 | # Plot data and capture styles once for each label |
| 225 | for label, df in self.dfs: |
| 226 | line, = self.ax.plot(df[x_col], df[y_col], label=label) |
| 227 | line.set_visible(self.visible.get(label, True)) |
| 228 | plotted.append((label, line)) |
| 229 | |
| 230 | if label not in self.styles: |
| 231 | self.styles[label] = dict( |
| 232 | color=line.get_color(), |
| 233 | linestyle=line.get_linestyle(), |
| 234 | marker=line.get_marker(), |
| 235 | ) |
| 236 | |
| 237 | self.ax.set_xlabel(x_col) |
| 238 | self.ax.set_ylabel(y_col) |
| 239 | self.ax.set_title(f"{y_col} vs {x_col}") |
| 240 | |
| 241 | # Build legend from proxy artists so entries never disappear |
| 242 | proxies = [] |
| 243 | labels = [] |
| 244 | for label, line in plotted: |
| 245 | st = self.styles.get(label, {}) |
| 246 | proxy = Line2D( |
| 247 | [0], [0], |
| 248 | color=st.get("color", "k"), |
| 249 | linestyle=st.get("linestyle", "-"), |
| 250 | marker=st.get("marker", None), |
| 251 | ) |
| 252 | proxy.set_alpha(1.0 if line.get_visible() else 0.2) |
| 253 | proxies.append(proxy) |
| 254 | labels.append(label) |
| 255 | |
| 256 | leg = self.ax.legend(handles=proxies, labels=labels, loc="best", |
| 257 | fancybox=True, shadow=True) |
| 258 | |
| 259 | # IMPORTANT: legend clones the handles; attach pick + mapping to the cloned artists |
| 260 | legend_handles = self._legend_handles(leg) |
| 261 | for h, (label, line) in zip(legend_handles, plotted): |
| 262 | h.set_picker(5) # pickable handle |
| 263 | h._origline = line # map legend handle -> real line |
| 264 | h.set_alpha(1.0 if line.get_visible() else 0.2) |
| 265 | |
| 266 | # Also make legend text clickable and mapped to the real line |
| 267 | for t, (label, line) in zip(leg.get_texts(), plotted): |
| 268 | t.set_picker(True) |
| 269 | t._origline = line |
| 270 | |
| 271 | self.canvas.draw() |
| 272 | |
| 273 | def on_select(self, event): |
| 274 | # Redraw with same visibility choices |
no test coverage detected