Spyder环境下matplotlib事件处理与点拾取功能无法正常工作
问题原因
Spyder默认给IPython控制台配置的Matplotlib绘图后端是inline模式,该模式的运行逻辑是将绘图结果静态渲染后嵌入控制台输出区,不会启动独立的交互事件循环,plt.show()调用时不会阻塞脚本执行流程:脚本会直接跳过交互阶段跑完后续所有代码,绑定的鼠标点击回调函数根本没有被触发的机会,因此tin和tout始终保持初始值0,也无法在画布上拾取点。
而通过Anaconda PowerShell启动的IPython默认使用Qt5Agg这类交互式后端,plt.show()会阻塞主线程、维持窗口事件循环,直到手动关闭画布窗口才会继续执行后续代码,因此点拾取功能可以正常工作。
解决方法
两种方案选其一即可:
方案1:修改Spyder全局绘图配置(一劳永逸)
按以下步骤调整设置:
- 打开Spyder顶部菜单栏的
Tools→Preferences - 在左侧设置栏选择
IPython console,切换到右侧的Graphics标签页 - 将
Backend选项从默认的Inline修改为Qt5(匹配环境中已安装的PyQt5版本) - 点击
Apply保存设置,重启IPython控制台或重启Spyder后生效。
方案2:脚本内临时指定后端(不修改全局配置)
如果不想改动Spyder全局设置,直接在脚本最开头、导入matplotlib.pyplot之前添加后端指定代码即可,修改后的完整示例代码如下:
import matplotlib # 必须在import pyplot之前执行后端设置 matplotlib.use('Qt5Agg') import numpy as np import matplotlib.pyplot as plt fig, ax = plt.subplots(2, 2) ax[0, 0].plot(np.random.rand(10)) ax[0, 1].plot(np.random.rand(10)) ax[1, 0].plot(np.random.rand(10)) ax[1, 1].plot(np.random.rand(10)) def onclick(event): if onclick.index == 0: onclick.tin = np.round(event.xdata, 3) else: onclick.tout = np.round(event.xdata, 3) print('tin = ', onclick.tin, 'tout =', onclick.tout, end='\r') onclick.index = (onclick.index+1) % 2 onclick.index = 0 onclick.tin = 0 onclick.tout = 0 cid = fig.canvas.mpl_connect('button_press_event', onclick) # 如果改完后端仍出现脚本提前执行的问题,可将下一行改为plt.show(block=True)强制阻塞 plt.show() fig.canvas.mpl_disconnect(cid) tin = onclick.tin tout = onclick.tout print('\n\n tin = ', tin, 'tout =', tout, end='\r')
内容的提问来源于stack exchange,提问作者Barzi2001
相关产品推荐
相关产品推荐

