'Tkinter DPI bug depends on how import is entered?
I have a weird question. In essence: why does the way I enter the pyplot import
line into iPython influence my plot?!
Try this (on Windows 10):
- Use a high-DPI main monitor set to 200%
- Start a fresh iPython console
- Enter the three blocks of code below one by one, using any of these ways for any block:
- just typing, OR
- pasting: pressing Ctrl+V, OR
- pasting: clicking the right mouse button, OR
- pressing Up to get it from history
- To execute each block, just press Enter
- Check whether the whole axis is visible
- Close iPython and try again
The Python code:
import matplotlib as mpl
mpl.use('TkAgg')
import matplotlib.pyplot as plt
from ctypes import windll
windll.shcore.SetProcessDpiAwareness(2)
fig = plt.figure()
w = fig.canvas.manager.window
print(w.winfo_screenwidth(), w.winfo_screenheight())
w.wm_geometry('1600x800+60+0')
fig.canvas.flush_events()
plt.plot(1, 'x')
plt.show(block=False)
Now the result depends on how the first two blocks have been entered. If one or both of them used option 1 or 2, an incorrect monitor size is reported (1920x1080), but I do get a 'correct' plot (with tiny fonts):
If both import lines have been entered using option 3 or 4 however, the reported monitor size is correct (3840x2160), but I get incorrectly sized/zoomed plots (with normal font size):
The behavior depends on how import
lines (or the 'run script' they are in) are entered!? Not how they are run, that's just Enter.
Any idea what causes this? Or how to fix it? Other than remembering to always do Ctrl+V instead of history or right click...
Changing the window size manually a bit afterwards makes the axis fit inside the window. But I would like to script it. And the manual resize does not fix all differences: options 1 and 2 keep using tiny fonts.
Explicitly resetting SetProcessDpiAwareness(0)
prevents the issue (1 and 2 keep it): monitor reported as 1920x1080, axes fit inside figure, but a larger window and normal size fonts.
Specifying dpi=192
(or something) explicitly with plt.figure()
does not help or change anything.
The used backend is the TkAgg Windows default. The exact same happens with TkCairo. The WxAgg and QtAgg alternatives work ok, using window.SetClientSize(1600, 800)
resp. manager.resize(1600, 800)
(they work like SetProcessDpiAwareness(0)
). So I guess the issue is specific to tkinter
.
Using python.exe (instead of ipython.exe) always shows the incorrect version. AFAICS I have not changed the High DPI compatibility settings for iPython.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|