【问题标题】:Embedding second animated graph to PyQt5 GUI将第二个动画图嵌入到 PyQt5 GUI
【发布时间】:2019-09-02 13:19:26
【问题描述】:

我想在 GUI 中添加第二个动画图表,其中包含我的第一个动画图表,两个图表同时动画,但我不确定如何。

这是我的代码:

import sys
import numpy as np
from matplotlib.backends.qt_compat import QtWidgets
from matplotlib.backends.backend_qt5agg import (
        FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure
from matplotlib import animation


class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self._main = QtWidgets.QWidget()
        self.setCentralWidget(self._main)
        layout = QtWidgets.QVBoxLayout(self._main)

        self.fig = Figure(figsize=(5, 3))
        self.canvas = FigureCanvas(self.fig)
        layout.addWidget(self.canvas)
        self.addToolBar(NavigationToolbar(self.canvas, self))

        self.setup()

    def setup(self):
        self.ax = self.fig.subplots()
        self.ax.set_aspect('equal')
        self.ax.grid(True, linestyle = '-', color = '0.10')
        self.ax.set_xlim([-15, 15])
        self.ax.set_ylim([-15, 15])

        self.scat = self.ax.scatter([], [], c=(0.9, 0.1, 0.5),  zorder=3)
        self.scat.set_alpha(0.8)

        self.anim = animation.FuncAnimation(self.fig, self.update,
                                                 frames = 720, interval = 10)

    def update(self, i):

        self.scat.set_offsets(([np.cos(np.radians(i))*7.5, np.sin(np.radians(i))*7.5], [0,0]))

if __name__ == "__main__":
    qapp = QtWidgets.QApplication(sys.argv)
    app = ApplicationWindow()
    app.show()
    qapp.exec_()

这里是一些示例代码,在同一个窗口中有两个图表(就像我想要的那样) 在这里,他们对动画图使用_update_canvas 函数,在应用程序窗口类中绘制另一个图(这只是一个静态图)。 我正在使用update 绘图函数来为我的图表设置动画,我需要 second update 绘图函数吗?怎么样?

示例代码:

import sys
import time
import numpy as np

from matplotlib.backends.qt_compat import QtCore, QtWidgets, is_pyqt5
if is_pyqt5():
    from matplotlib.backends.backend_qt5agg import (
        FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
else:
    from matplotlib.backends.backend_qt4agg import (
        FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure


class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self._main = QtWidgets.QWidget()
        self.setCentralWidget(self._main)
        layout = QtWidgets.QVBoxLayout(self._main)

        static_canvas = FigureCanvas(Figure(figsize=(5, 3)))
        layout.addWidget(static_canvas)
        self.addToolBar(NavigationToolbar(static_canvas, self))

        dynamic_canvas = FigureCanvas(Figure(figsize=(5, 3)))
        layout.addWidget(dynamic_canvas)
        self.addToolBar(QtCore.Qt.BottomToolBarArea,
                        NavigationToolbar(dynamic_canvas, self))

        self._static_ax = static_canvas.figure.subplots()
        t = np.linspace(0, 10, 501)
        self._static_ax.plot(t, np.tan(t), ".")

        self._dynamic_ax = dynamic_canvas.figure.subplots()
        self._timer = dynamic_canvas.new_timer(
            100, [(self._update_canvas, (), {})])
        self._timer.start()

    def _update_canvas(self):
        self._dynamic_ax.clear()
        t = np.linspace(0, 10, 101)
        # Shift the sinusoid as a function of time.
        self._dynamic_ax.plot(t, np.sin(t + time.time()))
        self._dynamic_ax.figure.canvas.draw()


if __name__ == "__main__":
    qapp = QtWidgets.QApplication(sys.argv)
    app = ApplicationWindow()
    app.show()
    qapp.exec_()

【问题讨论】:

    标签: python matplotlib graph pyqt pyqt5


    【解决方案1】:

    要嵌入多个动画图表,您需要创建多个绘图对象(FigureFigureCanvas),然后将每个对象添加到QVBoxLayout。如果要水平显示,可以使用QHBoxLayout。每个绘图对象都有自己的子图、网格和数据。要更新每个绘图的数据,您需要每个绘图都有其单独的绘图更新函数,您可以将其传递给animation.FuncAnimation 处理程序。因此,在您的情况下,要拥有两个动画图,您将需要两个更新绘图函数。

    from matplotlib.figure import Figure
    from matplotlib import animation
    import numpy as np
    import sys, matplotlib
    from PyQt5 import QtWidgets, QtCore
    from matplotlib.backends.backend_qt5agg import (FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
    
    class ApplicationWindow(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
            self._main = QtWidgets.QWidget()
            self.setCentralWidget(self._main)
            layout = QtWidgets.QVBoxLayout(self._main)
    
            # Configure figure 1 
            self.fig1 = Figure(figsize=(5, 3))
            self.canvas1 = FigureCanvas(self.fig1)
    
            # Configure figure 2
            self.fig2 = Figure(figsize=(5, 3))
            self.canvas2 = FigureCanvas(self.fig2)
    
            layout.addWidget(self.canvas1)
            layout.addWidget(self.canvas2)
            self.addToolBar(NavigationToolbar(self.canvas1, self))
            self.addToolBar(QtCore.Qt.BottomToolBarArea, NavigationToolbar(self.canvas2, self))
    
            self.setup()
    
        def setup(self):
            # Plot 1 (top)
            self.ax1 = self.fig1.subplots()
            self.ax1.set_aspect('equal')
            self.ax1.grid(True, linestyle = '-', color = '0.10')
            self.ax1.set_xlim([-15, 15])
            self.ax1.set_ylim([-15, 15])
    
            # Plot 2 (bottom)
            self.ax2 = self.fig2.subplots()
            self.ax2.set_aspect('equal')
            self.ax2.grid(True, linestyle = '-', color = '0.10')
            self.ax2.set_xlim([-15, 15])
            self.ax2.set_ylim([-15, 15])
    
            self.scat1 = self.ax1.scatter([], [], c=(0.9, 0.1, 0.5),  zorder=3)
            self.scat1.set_alpha(0.8)
    
            self.scat2 = self.ax2.scatter([], [], c=(0.9, 0.1, 0.5),  zorder=3)
            self.scat2.set_alpha(0.8)
    
            self.anim1 = animation.FuncAnimation(self.fig1, self.update1,frames = 720, interval = 10)
            self.anim2 = animation.FuncAnimation(self.fig2, self.update2,frames = 720, interval = 10)
    
        # Update data for plot 1
        def update1(self, i):
            self.scat1.set_offsets(([np.cos(np.radians(i))*7.5, np.sin(np.radians(i))*7.5], [0,0]))
    
        # Update data for plot 2
        def update2(self, i):
            self.scat2.set_offsets(([np.cos(np.radians(i))*7.5, np.sin(np.radians(i))*7.5], [0,0]))
    
    if __name__ == "__main__":
        qapp = QtWidgets.QApplication(sys.argv)
        app = ApplicationWindow()
        app.show()
        qapp.exec_()
    

    【讨论】:

    • 使用单个FuncAnimation 会更有效。
    • @nathancy 非常感谢,这对我很有帮助,我理解得更好,我可以将相同的属性行用于第 3 或第 4 行(我现在刚刚尝试过)。非常感谢!
    【解决方案2】:

    您需要两个单独的画布和两个单独的图形是否有特定原因?如果不是,那么我同意 ImportanceOfBeingErnest 的评论,并且您应该只创建一个带有 2 个子图的图形/画布,并调用一个更新函数来更新两个轴的内容。

    本质上,您的问题将与this one 重复,除了您将动画嵌入到 Qt 应用程序中。

    import sys
    import time
    import numpy as np
    
    from matplotlib.backends.qt_compat import QtCore, QtWidgets, is_pyqt5
    if is_pyqt5():
        from matplotlib.backends.backend_qt5agg import (
            FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
    else:
        from matplotlib.backends.backend_qt4agg import (
            FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
    from matplotlib.figure import Figure
    
    
    class ApplicationWindow(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
            self._main = QtWidgets.QWidget()
            self.setCentralWidget(self._main)
            layout = QtWidgets.QVBoxLayout(self._main)
    
            self.fig = Figure(figsize=(5, 6))
            self.canvas = FigureCanvas(self.fig)
            layout.addWidget(self.canvas)
            self.addToolBar(QtCore.Qt.BottomToolBarArea,
                            NavigationToolbar(self.canvas, self))
    
            self._axs = self.fig.subplots(2, 1)
    
            self._timer = self.canvas.new_timer(
                100, [(self._update_canvas, (), {})])
            self._timer.start()
    
        def _update_canvas(self):
            [ax.clear() for ax in self._axs]
            t = np.linspace(0, 10, 501)
            self._axs[0].plot(t, np.tan(t + time.time()), ".")
    
            t = np.linspace(0, 10, 101)
            self._axs[1].plot(t, np.sin(t + time.time()))
            self.canvas.draw()
    
    
    if __name__ == "__main__":
        qapp = QtWidgets.QApplication(sys.argv)
        app = ApplicationWindow()
        app.show()
        qapp.exec_()
    

    【讨论】:

      猜你喜欢
      • 2019-04-08
      • 1970-01-01
      • 1970-01-01
      • 2017-11-26
      • 2021-11-29
      • 2017-12-23
      • 1970-01-01
      • 1970-01-01
      • 2014-11-16
      相关资源
      最近更新 更多