带有 Matplotlib 的 PyQT5 插槽没有效果

Posted

技术标签:

【中文标题】带有 Matplotlib 的 PyQT5 插槽没有效果【英文标题】:PyQT5 slot with Matplotlib has no effect 【发布时间】:2017-11-22 15:21:56 【问题描述】:

我正在尝试实现一个插槽方法,该方法将清除作为 QtWidget 一部分的 matplotlib 图。我在 Windows 7 和 10 上尝试了 Python 3.6 和 3.5,我得到了相同的行为。

我的问题是,当从主代码块或在绘制图形的类中调用擦除方法时,我可以完美地清除图形。但是每当这个相同的方法作为一个 PyQT 信号的槽被调用时,槽实际上是被激活的,但是对 fig.clf() 的调用并没有清除这个数字。

下面的代码显示了问题:

import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QApplication,QMainWindow, QSizePolicy,QWidget,QVBoxLayout, QPushButton
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg  import FigureCanvasQTAgg as FigureCanvas


class Graphpopulate(FigureCanvas):

    def __init__(self, parent=None):
        self.fig = Figure(figsize=(6,4))
        self.ax = self.fig.add_axes([0.07, 0.16, 0.95, 0.95])  # fraction of figure size  #
        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)
        x = [2000, 2001, 2002, 2003, 2004]
        y = [10, 20, 30, 40, 50]
        self.plt = self.ax.plot(x, y)

        # self.wipe()  # OK This one works as well
        # self.plt.close(self.fig) # close the app, does not only clear figure

    def wipe(self):
        print('wipe start')
        # del self.fig  # close the app  on second call, does not only clear figure !!
        # self.plt.close(fig) # close the app, does not only clear figure
        rc = self.fig.clf()
        print('return code from clf()  '+ str(rc))
        print('wipe stop')


if __name__ == '__main__':

    # create main window
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    MainWindow.resize(800, 600)

    # create widget to be used by MathPlotlib
    WidgetMatplot = QWidget(MainWindow)
    WidgetMatplot.setGeometry(QRect(10, 40, 500, 500))

    # create Push Button with clicked signal linked to GraphPopulate.wipe() slot
    button = QPushButton(MainWindow)
    button.setText("Push Me !")

    # add widget to vertical box layout
    hbox = QVBoxLayout(MainWindow)
    hbox.addWidget(WidgetMatplot)
    hbox.addWidget(button)

    g = GraphPopulate(WidgetMatplot)

    button.pyqtConfigure(clicked=g.wipe)  # NOT OK !!!!!!! g.wipe is triggered as prints statements show
                                          #  on console but self.fig.clf() has no effect

    MainWindow.show()
    # g.wipe()  # OK
    sys.exit(app.exec_())

我已将 cmets 放在声明中,如果未注释实际上是清除数字或关闭整个应用程序。

看起来“matplotlib 上下文”在从signa-slot connect 调用时与从其他调用不同。

可能是我错过了一些琐碎的事情。如果很抱歉,但我自己找不到任何调查方向......所以我依靠你们来发现它。

谢谢 - 蒂博

【问题讨论】:

【参考方案1】:

在您的代码中,该图已成功清除。您只是看不到它,因为没有人告诉该图形需要重新绘制。

如果你重新绘制这个图形,你会发现它确实是空的。

def wipe(self):
    self.fig.clf()
    self.fig.canvas.draw_idle()

【讨论】:

谢谢!那么 MainWindow.show() 之后的主块中的 g.wipe() 怎么不需要这样的绘图指令呢?因为它包含在主程序循环中而不是插槽方法中? 该图首先绘制在app.exec_()上,即你调用wipe之后。所以此时人影已经清零了。当你按下按钮时,图形已经被绘制,所以你需要重新绘制它才能看到变化。 好的,谢谢,我错误地假设绘图是在 show () 函数执行时完成的。因此我的问题

以上是关于带有 Matplotlib 的 PyQT5 插槽没有效果的主要内容,如果未能解决你的问题,请参考以下文章

从 Matplotlib 图中提取信息并将其显示在 PyQt5 GUI 中

网址未使用不同类中的信号和插槽 PyQt5 定义

Matplotlib 将图形嵌入到 UI PyQt5

PyQt5 结合 matplotlib 时,如何显示其 NavigationToolbar

PYQT5 信号和插槽 [重复]

PyQt5 线程、信号和插槽。连接错误