Håkon Hægland
Håkon Hægland

Reputation: 40718

How to get width of matplotlib figure window before entering the event loop?

I am trying to determine the size of the current matplotlib figure window, such that I can reposition it correctly on the screen. This must be done before entering the event loop ( i.e. before calling plt.show() ). Here is an example:

import matplotlib
import matplotlib.pyplot as plt

def print_info(window):
    print("screen width: {}".format(window.winfo_screenwidth()))
    print("window width: {}".format(window.winfo_width()))
    return

matplotlib.use('TkAgg')
fig, axes = plt.subplots()
axes.plot([1, 2, 3], [1, 4, 9], 'ro', label='Test')
axes.set_title('Test curve')
# plt.draw()  # <-- this has no effect
# fig.canvas.draw_idle()  # <-- this has no effect
window = plt.get_current_fig_manager().window
# window.update() # <-- this has no effect
fig.canvas.mpl_connect('key_press_event', lambda event: print_info(window))
#plt.pause(0.000001) # only entering the tk/pyplot event loop forces update
print_info(window)
plt.show()

The output is:

screen width: 1920
window width: 1

If I uncomment the plt.pause(...) call, it works fine (but I get a warning):

/home/hakon/.pyenv/versions/3.6.1/lib/python3.6/site-packages/matplotlib/backend_bases.py:2453: MatplotlibDeprecationWarning: Using default event loop until function specific to this GUI is implemented
  warnings.warn(str, mplDeprecation)
screen width: 1920
window width: 640

Questions:

Upvotes: 1

Views: 2287

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339062

This warning is a big mystery. It always appears when using interactive mode. I never experienced any problems using interactive mode despite the warning, so I would recommend just ignoring it. The approach seems ok.

An alternative to obtain the figure size would be (see this question) to multiply the figure size in inches (fig.get_size_inches()) with the dpi (fig.dpi).

import matplotlib
matplotlib.use('TkAgg') # <- note that this must be called before pyplot import.
import matplotlib.pyplot as plt

fig, axes = plt.subplots()
axes.plot([1, 2, 3], [1, 4, 9], 'ro', label='Test')
axes.set_title('Test curve')

size = fig.get_size_inches()*fig.dpi
print("figure width: {}, height: {}".format(*size))

plt.show()

This prints figure width: 640.0, height: 480.0 for the default settings of 6.4 and 4.8 inch and 100 dpi.

To find the screen width and height, you may use e.g. Tkinter

import Tkinter as tk # use tkinter for python 3
root = tk.Tk()
width = root.winfo_screenwidth()
height = root.winfo_screenheight()
print("screen width: {}, height: {}".format(width, height))

which prints e.g. screen width: 1920, height: 1080.

Upvotes: 2

Related Questions