Python调用matplotlib ginput报QTimer负超时冻结如何解决
问题现象
使用ginput从系列绘图中读取(x, y)坐标值时,程序直接冻结无响应,抛出如下报错:
QTimer::singleShot: Timers cannot have negative timeouts
问题根因
ginput函数的第二个入参是超时时间(单位:秒),示例代码中传入-1作为超时值,在Matplotlib的Qt后端逻辑中,该负值会被直接传递给Qt的QTimer组件,而QTimer不支持负超时参数,直接触发报错。- 代码执行顺序错误:
plt.show()被放在ginput调用之后,窗口未完成渲染就启动取点逻辑,会进一步导致程序无响应。 - 循环中未清空/新建画布,多次绘图会叠加在同一个图层上,也会干扰ginput的正常运行。
复现问题的原始代码
import numpy as np import matplotlib.pyplot as plt for loop in range(10): x = np.linspace(1,10) y = np.sin(loop*x) plt.plot(x, y) points = plt.ginput(-1, -1) print(points) plt.show()
修复方案
- 调整
ginput参数:如果需要无限等待用户输入、不设置超时,将第二个参数设置为timeout=0即可;第一个参数n=-1是合法取值,代表不限制取点数量,用户按回车/鼠标中键即可结束当前轮取点。 - 调整执行顺序:每次循环新建独立画布,绘图完成后先调用
plt.draw()完成渲染,再启动ginput取点,取点完成后关闭当前画布再进入下一轮循环,不要在ginput之后调用plt.show()。
修复后可运行代码
import numpy as np import matplotlib.pyplot as plt for loop in range(10): x = np.linspace(1, 10, 100) y = np.sin(loop * x) plt.figure() plt.plot(x, y) plt.draw() # 按回车键即可结束当前画布取点,自动进入下一轮 points = plt.ginput(n=-1, timeout=0) print(points) plt.close()
内容的提问来源于stack exchange,提问作者Amin
相关产品推荐
相关产品推荐

