为什么matplotlib按钮不能与pyqt5一起工作?

t30tvxxf  于 2022-12-23  发布在  其他
关注(0)|答案(1)|浏览(132)

现在我想使用matplotlib的自定义按钮功能,请参考以下文档:https://matplotlib.org/stable/gallery/widgets/buttons.html,它工作得很好。但是当我想把它和PyQt5结合起来的时候,我首先创建了一个主窗口,里面有一个按钮。当按钮被点击的时候,会弹出一个图,但是图中的按钮失去了响应。代码如下所示:

import sys

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import Button
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QApplication, QPushButton, QWidget

class Index:
    ind = 0

    def __init__(self, l, freqs):
        self.l = l
        self.freqs = freqs

    def next(self, event):
        self.ind += 1
        i = self.ind % len(self.freqs)
        ydata = np.sin(2 * np.pi * self.freqs[i] * t)
        self.l.set_ydata(ydata)
        plt.draw()

    def prev(self, event):
        self.ind -= 1
        i = self.ind % len(self.freqs)
        ydata = np.sin(2 * np.pi * self.freqs[i] * t)
        self.l.set_ydata(ydata)
        plt.draw()

class App(QWidget):

    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 button - pythonspot.com'
        self.left = 10
        self.top = 10
        self.width = 320
        self.height = 200
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        button = QPushButton('PyQt5 button', self)
        button.setToolTip('This is an example button')
        button.move(100, 70)
        button.clicked.connect(self.on_click)

        self.show()

    @pyqtSlot()
    def on_click(self):
        freqs = np.arange(2, 20, 3)
        fig, ax = plt.subplots()
        fig.subplots_adjust(bottom=0.2)
        t = np.arange(0.0, 1.0, 0.001)
        s = np.sin(2 * np.pi * freqs[0] * t)
        l, = ax.plot(t, s, lw=2)

        callback = Index(l, freqs)
        axprev = fig.add_axes([0.7, 0.05, 0.1, 0.075])
        axnext = fig.add_axes([0.81, 0.05, 0.1, 0.075])
        bnext = Button(axnext, 'Next')
        bnext.on_clicked(callback.next)
        bprev = Button(axprev, 'Previous')
        bprev.on_clicked(callback.prev)

        plt.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

我想知道为什么?
在这个问题中:matplotlib event doesn't work when I use button clicked connect in pyqt5,我看到好像是自己定义了一个窗口,然后嵌入matplotlib,但是我不明白为什么有文档说一定要这么做?
我试过Macos、linux、windows,在macos下都能用,但是在linux和windows下按钮都没有React,我怀疑和QCoreApplication::exec有关:事件循环已经在运行了,但是我不明白为什么qt问题会影响到matplotlib,matplotlib的信号注册到pyqt5了吗?

hfyxw5xn

hfyxw5xn1#

是,是,您无需使用PlotEx,参考Why aren't the matplotlib checkboxes working in pyQt5?
我明白了,是因为按钮是局部变量,我需要一个更大的作用域。
正确代码是:

import sys

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import Button
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QApplication, QPushButton, QWidget

class Index:
    ind = 0

    def __init__(self, l, freqs, t):
        self.l = l
        self.freqs = freqs
        self.t = t

    def next(self, event):
        self.ind += 1
        i = self.ind % len(self.freqs)
        ydata = np.sin(2 * np.pi * self.freqs[i] * self.t)
        self.l.set_ydata(ydata)
        plt.draw()

    def prev(self, event):
        self.ind -= 1
        i = self.ind % len(self.freqs)
        ydata = np.sin(2 * np.pi * self.freqs[i] * self.t)
        self.l.set_ydata(ydata)
        plt.draw()

class App(QWidget):

    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 button - pythonspot.com'
        self.left = 10
        self.top = 10
        self.width = 320
        self.height = 200
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        button = QPushButton('PyQt5 button', self)
        button.setToolTip('This is an example button')
        button.move(100, 70)
        button.clicked.connect(self.on_click)

        self.show()

    @pyqtSlot()
    def on_click(self):
        freqs = np.arange(2, 20, 3)
        fig, ax = plt.subplots()
        fig.subplots_adjust(bottom=0.2)
        t = np.arange(0.0, 1.0, 0.001)
        s = np.sin(2 * np.pi * freqs[0] * t)
        l, = ax.plot(t, s, lw=2)

        callback = Index(l, freqs, t)
        axprev = fig.add_axes([0.7, 0.05, 0.1, 0.075])
        axnext = fig.add_axes([0.81, 0.05, 0.1, 0.075])
        bnext = Button(axnext, 'Next')
        bnext.on_clicked(callback.next)
        bprev = Button(axprev, 'Previous')
        bprev.on_clicked(callback.prev)

        plt.bnext = bnext
        plt.bprev = bprev

        plt.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

不同之处在于添加(并修复一些错误):

plt.bnext = bnext
        plt.bprev = bprev

相关问题