Changing matplotlib backend to Qt alters Tkinter windows

Hi folks, I’ve been writing a program using both Tkinter and matplotlib in a Jupyter Notebook in VS Code, and noticed strange (possibly unintended) behavior when switching the matplotlib backend to Qt via %matplotlib qt.

With the following code, I see that without using %matplotlib qt, I get some incorrect results about monitor resolution and DPI (the monitor is 28"@4K, should have a DPI of 157).

import ctypes
from tkinter import Tk

root = Tk()

width = root.winfo_screenwidth()
height = root.winfo_screenheight()

print(width, height)
print(root.winfo_fpixels('1i'))

Output: 
1920 1080
96.0

If I then run this code:

import ctypes
from tkinter import Tk
%matplotlib qt

root = Tk()

width = root.winfo_screenwidth()
height = root.winfo_screenheight()

print(width, height)
print(root.winfo_fpixels('1i'))

Output: 
3840 2160
192.0

I don’t even need to import matplotlib at all into my code, simply writing that line changes the output.

I ran the following code in a terminal:

from tkinter import Tk
import matplotlib

matplotlib.use('qtagg')

root = Tk()

width = root.winfo_screenwidth()
height = root.winfo_screenheight()

print(width, height)
print(root.winfo_fpixels('1i'))

Output: 
1920 1080
96.0

and as you can see, I got a different result. Something tells me that there is a discrepancy between using %matplotlib qt and using matplotlib.use('qtagg'), even though the documentation does not indicate that there should be any difference.

Does anyone know what is happening here?

The %matplotlib magic is provided by IPython, not Matplotlib, so it could be doing anything really. matplotlib.use('qtagg') doesn’t really do anything except set the rcParam for the next use. Since you didn’t create any windows, it’s really done nothing.

To actually make the backend load, use matplotlib.pyplot.switch_backend(), or to be absolutely sure, create a Figure.

I’d assume that actually loading Qt will set something that affects Tk, but I can’t say what.

Maybe some part of it, but I know there is a specific repo on the Matplotlib developers Github page called ipympl that is for integrating Matplotlib into Jupyter notebooks. Would that not be where the specific magic command is defined?

I’m not particularly concerned about getting a backend properly loaded, I am just confused why the magic is causing the difference. Curiosity killed the cat and whatnot.

That repo provides a backend with integration to IPython; the magic for selecting backends is still part of IPython.

Oh interesting. Thanks for clarifying! Where would I look to see where that magic is defined?

Somewhere in IPython presumably.