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

Today I updated matplotlib to version 2.0.2 after not updating for maybe 3 years.

Now the problem I have is that on interactive plots, the window always pops out to the front, as if it makes the matplotlib plot window pop up, since the active behavior has become the default behavior.

How can I disable this? I don't want the window to go forward every 5 seconds and rise above my text editor, browser, ...

I want it to remain in the z-order where I placed it, whether in front of or behind the active window.

I believe the following commit, dated January 31, 2016, is responsible for this problematic behavior: tkagg: bring up every new window; partially of address No. 596

Found a relevant comment on Github https://github.com/matplotlib/matplotlib/issues/596#issuecomment-305298577

it looks like this is causing my challenge plt.pause

, not the challenge plt.plot

.

+8


source to share


4 answers


Backend change

The problem seems to be present only when using the backend Tk

. Using the backend Qt

, the window will stay where it was when updated with plt.pause

.

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

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

      

Modification plt.pause



If changing the backend is not possible, the following may help. The reason the window pops up constantly forwards is the plt.pause

caller plt.show()

inside. Therefore, you implement your own function pause

without calling show

. To do this, you must first switch to interactive mode plt.ion()

and then call at least once plt.show()

. After that, you can update the graph using the custom function mypause

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)

      

Use animation

.

Finally, using a class matplotlib.animation

will make all of the above obsolete. An example for is matplotlib.animation.FuncAnimation

shown on the matplotlib page .

+13


source


I had the same problem on Mac. I'm not sure if this is the best approach, but instead of using it, plt.pause(0.001)

I switched to fig.canvas.start_event_loop(0.001)

to update every frame in my animation. This allows the windows to remain in the background.



+3


source


I rewrote the code to use matplotlib.animation

using this documentation page https://matplotlib.org/devdocs/api/animation_api.html#module-matplotlib.animation

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

which talks about matplotlib.pyplot.pause

This can be used for rough animation. For more complex animations see matplotlib.animation.

This feature is experimental; its behavior may be changed or expanded in a future release.

0


source


It is April 2019 and the mypause () function (copied from modern pyplot implementation) for Matplotlib 3.0.3 should look 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 suit 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)

      

If fig is your object shape. In both cases, nothing worked. According to the animation documentation , this is exactly what FuncAnimation does.

0


source







All Articles