我有一个允许用户点击数据点的图表。然后它会生成一个连续的循环,应该通过单击关闭按钮来关闭它。下面的示例将每1秒触发一次“Still Looping”打印消息。然后我创建了一个按钮,希望通过将loopBool更改为True来关闭循环。但它不起作用,因为一旦循环开始,我无法与数字窗口交互。我怎么解决这个问题?非常感谢
import numpy as np
from matplotlib import pyplot as plt
import time
import matplotlib.widgets as widgets
fig, ax = plt.subplots()
# it is not always column 0 and 1
sctPlot = ax.scatter([-0.3,0,0.3], [0.3,0.3,0.3], c="blue", picker = 2, s=[50]*3)
fig.subplots_adjust(bottom=0.3, left=0.1)
plt.grid(False)
plt.axis([-0.6, 0.6, -0.6, 0.6])
loopBool = True
def closeLooping(event):
global loopBool
loopBool = False
def looping(event):
global loopBool
while (loopBool == True):
print "Still Looping!"
time.sleep(1)
print "Stop!!"
axCloseButton = plt.axes([0.1, 0.15, 0.2, 0.06])
bClose = Button(axCloseButton, "Close", color = axcolor, hovercolor = '0.975')
bClose.on_clicked(closeLooping)
fig.canvas.mpl_connect('pick_event', looping)
答案 0 :(得分:2)
在我看来,陷入无限循环的进程在某种意义上与GUI不兼容。 GUI本身执行循环,检查并响应发生的事件。最好的解决方案可能是通过将代码部分转换为基于事件的代码来移除无限循环。
但是,我也找到了解决您实际问题的方法。我对所涉及的编程结构不是很熟悉,所以我不能告诉你这个解决方案的效率和优雅程度。关键是在一个单独的线程中运行你的无限循环,从而防止你的主python进程卡在循环中。这将使GUI保持响应。但是,如果您想在程序运行期间中断程序,这可能会导致问题。
代码:
color=axcolor
请注意,我更改了一些内容,因为您的确切代码似乎无法正常运行。我从Button
电话中删除了plt.show()
;我在事件连接之前添加了ipython
,否则我没有显示图形窗口(既不通过python
也不通过threading
)。
相关的添加是looping_pre
模块和looping
前端,它将Thread
函数称为单独的'pick_event'
。因此,looping
不会调用looping_pre
,而是调用ipython
。
此代码将(在reset
中运行时)显示图形窗口,单击数据开始循环,然后单击按钮停止循环。但是,当我按下ctrl + c时,循环继续运行,因为它是一个单独的线程。我只是设法使用global loopBool
来杀死它,从而删除了Thread
的值。指定deamon
应该start_time
ized 的注释行应该影响此行为(我的意思是这对我来说似乎合乎逻辑),但我没有看到任何影响。