Make interactive matplotlib window not pop to front on each update (Windows 7)

前端 未结 4 1287
北恋
北恋 2020-12-11 01:28

Today I upgraded matplotlib to version 2.0.2, after not upgrading for possibly 3 years.

Now I have the problem that in interactive plots the window always comes to t

相关标签:
4条回答
  • 2020-12-11 01:38

    Changing the backend

    The issue seems only present using the Tk backend. Using the Qt backend, the window would stay where it was while updating with plt.pause.

    To change the backend use those lines at the beginning of your script.

    import matplotlib
    matplotlib.use("Qt4agg") # or "Qt5agg" depending on you version of Qt
    

    Modifying plt.pause

    If changing the backend is not an option, the following might help. The cause of the window constantly popping up to the front comes from plt.pause calling plt.show() internally. You therefore implement you own pause function, without calling show. This requires to be in interactive mode plt.ion() first and then at least once call plt.show(). Afterwards you may update the plot with the custom mypause function as shown below.

    import matplotlib
    matplotlib.use("TkAgg")
    import matplotlib.pyplot as plt
    from time import time
    from random import random
    
    plt.ion()
    # set up the figure
    fig = plt.figure()
    plt.xlabel('Time')
    plt.ylabel('Value')
    
    plt.show(block=False)
    
    def mypause(interval):
        backend = plt.rcParams['backend']
        if backend in matplotlib.rcsetup.interactive_bk:
            figManager = matplotlib._pylab_helpers.Gcf.get_active()
            if figManager is not None:
                canvas = figManager.canvas
                if canvas.figure.stale:
                    canvas.draw()
                canvas.start_event_loop(interval)
                return
    
    
    t0 = time()
    t = []
    y = []
    while True:
        t.append( time()-t0 )
        y.append( random() )
        plt.gca().clear()
        plt.plot( t , y )
        mypause(1)
    

    Using an animation.

    Finally, using a matplotlib.animation class would render all of the above obsolete. An example for matplotlib.animation.FuncAnimation is shown on the matplotlib page.

    0 讨论(0)
  • 2020-12-11 01:40

    I had the same problem on the Mac. I'm not sure if this is the best approach, but instead of using plt.pause(0.001), I switched to fig.canvas.start_event_loop(0.001) to update each frame on my animation. This allows the windows to stay in the background.

    0 讨论(0)
  • 2020-12-11 01:51

    It is April 2019 and the mypause() function (copied from the upto date pyplot implementation) for Matplotlib 3.0.3 should look more like

    import time
    import matplotlib.pyplot as plt
    def mypause(interval):
        manager = plt._pylab_helpers.Gcf.get_active()
        if manager is not None:
            canvas = manager.canvas
            if canvas.figure.stale:
                canvas.draw_idle()        
            #plt.show(block=False)
            canvas.start_event_loop(interval)
        else:
            time.sleep(interval)
    

    After some testing (Qt5 backend/Spyder/Windows 7 64bit) the calls that do the trick for me are:

    #plt.pause(0.001) #Brings plot to foreground
    #fig.canvas.draw() #Does not work
    #plt.draw_all() #Does not work
    #plt.draw() #Does not work
    #fig.canvas.flush_events() #Updates only if I click the figure 
    #import time; time.sleep(0.001) #Does not help flush_events()
    #fig.canvas.draw_idle() #Does not work by itself
    #fig.canvas.start_event_loop(0.001) #Does not work by itself
    #mypause(0.001) #Works!
    
    #Works!
    fig.canvas.draw_idle()
    fig.canvas.start_event_loop(0.001)
    

    Were fig is your figure object. Either of both alone didn't work in my case. According to the animation documentation this is essentially what FuncAnimation does.

    0 讨论(0)
  • 2020-12-11 02:01

    I rewrote the code to use matplotlib.animation with the help from this documentation page https://matplotlib.org/devdocs/api/animation_api.html#module-matplotlib.animation

    I got to that page through this one https://matplotlib.org/devdocs/api/_as_gen/matplotlib.pyplot.pause.html

    which states the following about matplotlib.pyplot.pause

    This can be used for crude animation. For more complex animation, see matplotlib.animation.

    This function is experimental; its behavior may be changed or extended in a future release.

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