Matplotlib,关闭循环的按钮,python

2024-09-29 17:19:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个绘图,允许用户点击一个数据点。然后,它生成一个连续的循环,该循环应该通过单击close按钮来关闭。下面的示例将每1秒触发一条“仍在循环”的打印消息。然后我创建了一个按钮,希望通过将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)

Tags: importeventfalsetruetimematplotlibdefas
1条回答
网友
1楼 · 发布于 2024-09-29 17:19:47

在我看来,陷入无限循环的进程在某种意义上与GUI不兼容。gui本身执行一个循环,检查并响应发生的事件。最好的解决方案可能是删除无限循环,将该部分代码转换为基于事件的循环。在

不过,我也找到了解决你实际问题的办法。我不太熟悉所涉及的编程结构,所以我不能告诉您这个解决方案有多高效或优雅。关键是在一个单独的线程中运行无限循环,从而防止主python进程陷入循环中。这将使GUI保持响应。但是,如果您想在程序运行期间中断程序,这可能会导致问题。在

代码:

import time
import threading #this is new
import numpy as np
from matplotlib import pyplot as plt
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!!")

def looping_pre(event): #this is new
    thread = threading.Thread(target=looping, args=(event,))
    #thread.daemon = True   #might or might not be needed
    thread.start()

axCloseButton = plt.axes([0.1, 0.15, 0.2, 0.06])
bClose = widgets.Button(axCloseButton, "Close", hovercolor = '0.975')
bClose.on_clicked(closeLooping)
plt.show() #this is new

fig.canvas.mpl_connect('pick_event', looping_pre) #this is changed

请注意,我更改了一些事情,因为您的代码似乎无法正常运行。我从Button调用中删除了color=axcolor;并且在事件连接之前添加了一个plt.show(),否则我不会出现一个图窗口(既不是通过ipython,也不是通过python)出现的。在

相关的添加是threading模块和looping_pre前端,它将looping函数作为一个单独的Thread调用。因此,'pick_event'不调用looping,而是looping_pre。在

这段代码将(在ipython中运行时)显示figure窗口,在单击数据时开始循环,然后在单击按钮时停止循环。但是,当我按下ctrl+c时,循环继续进行,因为它是一个单独的线程。我只是通过使用reset来杀死它,从而删除了global loopBool的值。指定Thread是否应为deamon的注释行应影响此行为(我的意思是它在我看来是合乎逻辑的),但我没有看到任何效果。在

相关问题 更多 >

    热门问题