Getting blitting to work in funcAnimation embedded in PyQT4 GUI

后端 未结 2 960
独厮守ぢ
独厮守ぢ 2021-01-13 19:55

Starting with the working Matplotlib animation code shown below, my goal is to embed this animation (which is just a circle moving across the screen) within a PyQT4 GUI.

相关标签:
2条回答
  • 2021-01-13 20:10

    After some time I managed to recreate the animation by using the underlying functions directly and not using the animation wrapper:

    import sys
    from PyQt4 import QtGui, QtCore
    from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
    from matplotlib.figure import Figure
    from matplotlib.patches import Circle
    from matplotlib import animation
    from time import sleep
    
    class Window(QtGui.QDialog): #or QtGui.QWidget ???
    
        def __init__(self):
            super(Window, self).__init__()
            self.fig = Figure(figsize=(5, 4), dpi=100)
            self.canvas = FigureCanvas(self.fig)
            self.ax = self.fig.add_subplot(111)  # create an axis
            self.ax.hold(False)  # discards the old graph
            self.ax.set_aspect('equal', 'box')
            self.circle = Circle((0,0), 1.0, animated=True)
            self.ax.add_artist(self.circle)
            self.ax.set_xlim([0, 10])
            self.ax.set_ylim([-2, 2])
            self.button = QtGui.QPushButton('Animate')
            self.button.clicked.connect(self.animate)
    
            # set the layout
            layout = QtGui.QVBoxLayout()
            layout.addWidget(self.canvas)
            layout.addWidget(self.button)
            self.setLayout(layout)
            self.canvas.draw()
            self.ax_background = self.canvas.copy_from_bbox(self.ax.bbox)
    
        def animate(self):
            self.animate_loop(0)
    
        def animate_loop(self,begin):
            for i in range(begin,10):
                self.canvas.restore_region(self.ax_background)
                self.circle.center=(i,0)
                self.ax.draw_artist(self.circle)
                self.canvas.blit(self.ax.bbox)
                self.canvas.flush_events()
                sleep(0.1)
    
    def main():
    
        app = QtGui.QApplication(sys.argv)
        ex = Window()
        ex.show()
        sys.exit(app.exec_())
    
    if __name__ == '__main__':
        main() 
    

    Maybe this will be of use to you.

    0 讨论(0)
  • 2021-01-13 20:24

    After looking at the source code of the animation module, I realized that there is an error in the Animation class (the dictionary bg_cache is empty, when it is accessed for the first time with blitting switched on).

    This is fixed in the git version of matplotlib; however, in the most recent stable version 1.5.1, the bug is still present. You can either fix the bug in the matplotlib code itself or you can make a subclass to FuncAnimation. I chose that way, because it should still work after updating matplotlib.

    from matplotlib import animation
    
    class MyFuncAnimation(animation.FuncAnimation):
        """
        Unfortunately, it seems that the _blit_clear method of the Animation
        class contains an error in several matplotlib verions
        That's why, I fork it here and insert the latest git version of
        the function.
        """
        def _blit_clear(self, artists, bg_cache):
            # Get a list of the axes that need clearing from the artists that
            # have been drawn. Grab the appropriate saved background from the
            # cache and restore.
            axes = set(a.axes for a in artists)
            for a in axes:
                if a in bg_cache: # this is the previously missing line
                    a.figure.canvas.restore_region(bg_cache[a])
    

    Then, simpy use MyFuncAnimation instead of animation.FuncAnimation.

    Took me a while to figure it out, but I hope it helps anybody.

    0 讨论(0)
提交回复
热议问题