如何在Plotly+ipywidgets回调函数外访问点击坐标列表?
解决Plotly FigureWidget点击点后无法访问clicked列表的问题
你遇到的问题是在Jupyter环境中,使用FigureWidget的点击回调更新clicked列表后,无法在回调外部访问或打印最新的列表内容。以下是几种可行的解决方法:
问题重现代码
import numpy as np import plotly.graph_objects as go import ipywidgets as widgets x = np.random.uniform(-10, 10, size=50) y = np.sin(x) clicked = [] # 构建图表 fig = go.FigureWidget( [go.Scatter(x=x, y=y, mode="markers", name="base_points")] ) fig.update_layout(template="simple_white") out = widgets.Output(layout={"border": "1px solid black"}) out.append_stdout("Output appended with append_stdout\n") # 点击回调函数 @out.capture() def base_click(trace, points, selector): global clicked clicked.append(points.__dict__) fig.data[0].on_click(base_click) widgets.HBox([fig, out])
解决方法
1. 添加按钮触发查看点击数据
通过添加一个按钮控件,点击按钮时将clicked列表的内容输出到out组件,这样可以随时获取最新的点击记录:
import numpy as np import plotly.graph_objects as go import ipywidgets as widgets x = np.random.uniform(-10, 10, size=50) y = np.sin(x) clicked = [] fig = go.FigureWidget( [go.Scatter(x=x, y=y, mode="markers", name="base_points")] ) fig.update_layout(template="simple_white") out = widgets.Output(layout={"border": "1px solid black"}) out.append_stdout("点击图表点后,点击下方按钮查看坐标数据\n") # 回调函数:提取坐标并保存 def base_click(trace, points, selector): clicked.append({"x": points.xs[0], "y": points.ys[0]}) fig.data[0].on_click(base_click) # 按钮点击事件:输出clicked列表 def show_clicked_data(b): with out: print("当前已点击的坐标列表:") print(clicked) button = widgets.Button(description="查看点击数据") button.on_click(show_clicked_data) # 组装界面 widgets.VBox([widgets.HBox([fig, out]), button])
2. 在回调中直接输出坐标信息
修改回调函数,每次点击时直接将坐标数据输出到out组件,同时更新clicked列表,实现实时反馈:
import numpy as np import plotly.graph_objects as go import ipywidgets as widgets x = np.random.uniform(-10, 10, size=50) y = np.sin(x) clicked = [] fig = go.FigureWidget( [go.Scatter(x=x, y=y, mode="markers", name="base_points")] ) fig.update_layout(template="simple_white") out = widgets.Output(layout={"border": "1px solid black"}) out.append_stdout("点击图表点查看坐标数据\n") @out.capture() def base_click(trace, points, selector): coord = {"x": points.xs[0], "y": points.ys[0]} clicked.append(coord) print(f"新增点击坐标:{coord}") print(f"累计点击次数:{len(clicked)}") fig.data[0].on_click(base_click) widgets.HBox([fig, out])
3. 使用类封装状态(更规范的实现)
如果需要更复杂的交互逻辑,用类来封装点击状态和回调函数,避免使用global变量,代码结构更清晰:
import numpy as np import plotly.graph_objects as go import ipywidgets as widgets class ClickCoordinateTracker: def __init__(self): self.clicked_coords = [] # 初始化图表数据 x = np.random.uniform(-10, 10, size=50) y = np.sin(x) # 创建图表 self.fig = go.FigureWidget( [go.Scatter(x=x, y=y, mode="markers", name="base_points")] ) self.fig.update_layout(template="simple_white") # 创建输出组件 self.out = widgets.Output(layout={"border": "1px solid black"}) self.out.append_stdout("点击图表点记录坐标,点击按钮查看所有数据\n") # 绑定点击回调 self.fig.data[0].on_click(self._on_point_click) # 创建查看按钮 self.view_button = widgets.Button(description="查看所有点击坐标") self.view_button.on_click(self._show_all_coords) # 组装界面 self.ui = widgets.VBox([widgets.HBox([self.fig, self.out]), self.view_button]) def _on_point_click(self, trace, points, selector): coord = {"x": points.xs[0], "y": points.ys[0]} self.clicked_coords.append(coord) with self.out: print(f"已记录坐标:{coord}") def _show_all_coords(self, b): with self.out: print("\n所有已记录的点击坐标:") print(self.clicked_coords) # 实例化并显示界面 tracker = ClickCoordinateTracker() tracker.ui
内容的提问来源于stack exchange,提问作者Raxhacks
相关产品推荐
相关产品推荐

