PyQt5 matplotlib画图不刷新的解决方案

  

PyQt5与matplotlib是非常流行的Python图形库,但在使用matplotlib画图时会出现不刷新的情况。本篇攻略将详细介绍解决matplotlib画图不刷新的问题。

问题描述

使用matplotlib画图时,当图形放大或缩小时,图形内容会被拉伸或扭曲,而这是matplotlib内在的特性。当尝试通过PyQt5来实现图形界面时,我们通常会使用matplotlib嵌入到PyQt5的窗口控件中。但是,当窗口的大小改变时,控制台会输出一段错误信息"QPixmap: Cannot create a QPixmap when no GUI is being used",同时无法刷新图形。这是由于没有指定Qt的事件循环,导致matplotlib无法操作窗口。

解决方案

方法1:使用多线程

解决matplotlib无法操作窗口的一种方式是使用多线程。要在PyQt5中实现多线程,我们可以使用QThread类来创建一个新线程,并将matplotlib图形绘制在该线程中,以保证窗口控件能正常刷新。

from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import numpy as np

class PlotThread(QThread):
    plot_signal = pyqtSignal(object)

    def __init__(self, parent=None):
        super().__init__(parent)

    def run(self):
        fig = Figure()
        ax = fig.add_subplot(111)
        x = np.linspace(0, 10, 1000)
        y = np.sin(x)
        ax.plot(x, y)

        self.plot_signal.emit(fig)

以上是继承QThread类的一个简单的线程类。线程的run方法是需要重写的方法,调用plot_sin函数绘制图形。需要注意的是,由于不能直接操作matplotlib相关操作,我们需要使用pyqtSignal信号来将绘图数据发送回主线程。

class MyApp(QWidget):
    def __init__(self):
        super().__init__()

        self.button = QPushButton('Plot')
        self.canvas = FigureCanvas(Figure())
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.button)
        self.layout.addWidget(self.canvas)
        self.setLayout(self.layout)

        self.button.clicked.connect(self.plot)

    def plot(self):
        self.plot_thread = PlotThread()
        self.plot_thread.plot_signal.connect(self.plot_finished)
        self.plot_thread.start()

    def plot_finished(self, fig):
        self.canvas.figure = fig
        self.canvas.draw()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

以上是将QThread类线程嵌入到PyQt5的窗口控件中的简单示例。

方法2:使用timer槽函数

另一种使用PyQt5解决matplotlib画图不刷新的问题的方法是使用timer槽函数。QTimer类可以周期性地触发自定义的槽函数,这可以确保窗口控件能够定期刷新并绘制图像。

from PyQt5.QtCore import QTimer

class MyApp(QWidget):
    def __init__(self):
        super().__init__()

        self.button = QPushButton('Plot')
        self.canvas = FigureCanvas(Figure())
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.button)
        self.layout.addWidget(self.canvas)
        self.setLayout(self.layout)

        self.button.clicked.connect(self.plot)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_figure)

    def plot(self):
        # 绘制图形
        x = np.linspace(0, 10, 1000)
        y = np.sin(x)
        self.ax.plot(x, y)

        self.canvas.draw()

        # 启动定时器
        self.timer.start(100)

    def update_figure(self):
        # 刷新图形
        self.canvas.draw()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

结论

以上是两种可以解决PyQt5matplotlib画图不刷新的方法。第一种方法通过使用多线程实现图形绘制,而第二种方法则使用timer槽函数来定期刷新图形。无论哪种方法都可以让我们在PyQt5中使用matplotlib绘制图形,并实时刷新。

相关文章