如何用Matplotlib TextBox替代input实现图形化输入等待?
问题描述
需要在1D数据图中通过选择起止点提取线段,为每条选中的线段指定名称(用Matplotlib的TextBox替代终端input函数),但原代码无法复刻input的阻塞等待行为,导致程序会持续接收用户的点击操作,无法正常完成单条线段的命名流程。
解决方案
Matplotlib采用事件驱动的交互模式,无法直接实现类似input的阻塞逻辑,需要重构代码逻辑:将输入名称后的后续操作(存储线段信息、清理图形)放到TextBox的提交回调中,同时在等待输入时暂时禁用拾取事件,避免用户误操作。
修改后的完整代码
import numpy as np from matplotlib import pyplot as plt from matplotlib.widgets import TextBox def main(): # 预设要提取的线段数量 nSegment = 3 # 记录已选择的点数 nPointPressed = 0 # 存储当前线段的起始索引 I0 = 0 # 保存所有线段的信息:[名称, 起始索引, 结束索引] segment = [] # 存储拾取事件的连接ID,用于断开/重新连接事件 pick_cid = None def onpick(event): nonlocal nPointPressed, I0, fig, ax, pick_cid # 获取选中点的索引 ind = event.ind if len(ind) != 1: return # 绘制选中的点(红色空心圆) ax.plot(x[ind], y[ind], 'o', markerfacecolor='none', color='red', linewidth=2, markersize=5) plt.draw() nPointPressed += 1 # 偶数次点击为线段终点 if nPointPressed % 2 == 0: # 生成当前线段的索引区间 current_ij = np.linspace(I0, ind, dtype=int) # 绘制临时连线(绿色) ax.plot(x[current_ij], y[current_ij], color='green') plt.draw() # 断开拾取事件,防止用户在输入名称时继续点击 fig.canvas.mpl_disconnect(pick_cid) # 定义名称提交后的处理逻辑 def submit_name(name): nonlocal current_ij, pick_cid # 保存当前线段的信息 segment.append([name, current_ij[0], current_ij[-1]]) # 清理临时绘制的起点、终点和连线 pts = ax.get_lines() pts[-3].remove() # 删除起点标记 pts[-2].remove() # 删除终点标记 pts[-1].set_color("darkgreen") # 将临时连线改为深绿色,标记已确认 # 移除TextBox组件 text_box.remove() plt.draw() # 如果还未选够预设的线段数量,重新连接拾取事件 if len(segment) < nSegment: pick_cid = fig.canvas.mpl_connect("pick_event", onpick) else: # 选够线段后关闭窗口 plt.close() # 在图底部添加TextBox输入框 axbox = fig.add_axes([0.1, 0.05, 0.8, 0.075]) text_box = TextBox(axbox, "Segment name: ", textalignment="center") text_box.on_submit(submit_name) text_box.set_val("Unknown") # 设置默认名称 else: # 奇数次点击为线段起点,保存索引 I0 = ind # 生成示例数据 x = np.linspace(0, 2*np.pi, 20, dtype=float) y = np.sin(x) # 创建绘图窗口并连接拾取事件 fig, ax = plt.subplots() ax.plot(x, y, '-^', picker=True) pick_cid = fig.canvas.mpl_connect("pick_event", onpick) plt.show() # 打印最终提取的线段信息 for seg in segment: print(seg) if __name__ == '__main__': main()
关键修改说明
- 新增
pick_cid变量管理拾取事件的连接状态,在等待名称输入时断开事件,避免用户误操作 - 将线段的起止索引暂存到
current_ij,在TextBox的提交回调中完成信息存储和图形清理 - 提交名称后,根据是否已完成所有线段的提取,决定重新连接拾取事件或关闭窗口
- 移除
TextBox避免界面冗余,修改连线颜色区分已确认的线段
内容的提问来源于stack exchange,提问作者debronee101
相关产品推荐
相关产品推荐

