关于python:pylab.show()“ QCoreApplication :: exec:事件循环已在运行”

pylab.show() “QCoreApplication::exec: The event loop is already running”

我有一个使用matplotlib和QT4Agg后端的Python基本图像查看器程序。
功能之一是从2D-FFT生成2D功率谱,并将其放在一个图中的第二个图中。我想添加一个按钮,该按钮获取FFT图像并将其弹出到另一个窗口中,以便可以对其进行更详细的分析。

我的代码当前正在执行我需要做的所有事情,但同时也会向终端发出QT异常或某种警告(此操作正在OS X下运行):

" QCoreApplication :: exec:事件循环已在运行"

1
2
3
4
5
6
def popout(event):
    nfig, nfftax = pylab.subplots(1, 1)
    imgtoconv = getArr(files[imgindex])
    fftimg = np.abs(fftpack.fftshift(fftpack.fft2(imgtoconv)))**2
    nfftax.imshow(np.log10(fftimg), cmap=cm.Greys_r)
    pylab.show()

我定义了一个按钮,并通过Button.on_clicked(popout)链接到popout()函数
在程序的主循环中,将启动一个图形,并用两个图显示。所以pylab.show()已经被调用一次

我遇到的问题似乎是我再次调用pylab.show(),这正在生成异常或警告事件循环已启动。

我尝试使用pylab.draw()而不是pylab.show(),但是当我这样做时,单击按钮不会显示新图

是否有抑制此警告的简便方法?还是有另一种方法产生新图并使其可见而无需调用pylab.show()?

编辑:我还尝试在创建新图形和新轴后添加nfig.canvas.draw(),然后在popout()函数末尾调用pylab.draw()。这仍然没有显示新的数字onclick

EDIT2:切换为使用TKAgg后端并调用pylab.show()可使问题消失。关于为什么这只是QT4Agg后端中的一个问题有任何想法吗?


您是否尝试过使用ion()? 使用按钮回调中的多个图形时,我遇到了相同的问题。 对我来说,在popout()函数内部使用此代码可以解决问题:

1
2
3
4
5
6
7
8
9
10
11
import matplotlib.pyplot as p
import numpy as np
p.ion()
p.close(1)
p.close(2)

p.figure(1)
p.plot(np.random.normal(size=100))

p.figure(2)
p.plot(np.random.normal(size=100))

据我了解,这迫使matplotlib使用其自己的线程来处理所有图形,而不会与GUI的主循环冲突。 我关闭了数字以完全重置它们并释放了内存,但是p.clf()也可以工作。


如果您尝试在不使用ion()的情况下更新绘图,请使用此行进行更新

1
fig.canvas.draw()

示例程序在鼠标单击位置上绘制红点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import matplotlib.pyplot as plt

def plot_on_graph(ix, iy):
    global fig
    plt.scatter([ix],[iy], color='red')
    fig.canvas.draw()

def onclick(event):
    global ix,iy
    ix, iy = event.xdata, event.ydata
    print(ix, iy)
    plot_on_graph(ix, iy)

fig = plt.figure()
cid = fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()