You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add retina screen support for TkAgg backend #10388
The plots done with "TkAgg" backend look blurry on retina screen of my Mac Book Pro. The plots look good when I'm using the default "MaxOSX" backend. It would be nice to have retina-friendly output for "TkAgg" since I'm using the plots into a tkinter GUI app.
Code for reproduction
importmatplotlibmatplotlib.use('TkAgg') # Remove this to compare with MacOSX backendimportmatplotlib.pyplotaspltf=plt.figure(figsize=(6, 4))
a=f.add_subplot(111)
a.plot([1,2,3,4])
plt.show()
Actual outcome
The plots and toolbar look blurry on "TkAgg" backend.
Expected outcome
The plots and toolbar look sharp, just like on "MaxOSX" backend.
If I create a tkinter app, other elements like labels, menus are sharp as well, only the plot is blurry. This indicates that tkinter is capable of showing sharp graphics, the question is how to do it.
I could not find a way to show an image that is appropriately scaled on retina screen. Here is a demo app shows shows a gif image. The code root.tk.call('tk', 'scaling', 2.0) does not seem to do anything.
It looks like a tkinter issue/feature. I could not find a way to detect current screen scaling (2x on my screen) and then apply this when showing an image. Does anyone know where can I find people who maintain tkinter to report this?
I did a little googling and came up with nothing promising. From my reading, the 'scaling' parameter has little or nothing to do with retina support. What is happening now is that our Tkagg backend is seeing the retina display only in its pixel-doubled compatibility mode.
Gitk now looks nice and sharp on my retina display, though, including the history graph lines, which suggests that use of full resolution is not impossible. Gitk is using a Perl interface to Tk, I believe.
Tkinter is part of the regular python installation, but I haven't found any sign of a dedicated maintainer for it. Even the link to the tkinter wiki is now dead.
My computer system is Windows 10, 1709 .
The resolution is 2560*1440, DPI Zoom is 200%
I encounter a similar situation.
I encountered a similar situation
When I delete matplotlib.use('TkAgg')
The display is still vague,
The UI looks hazy on high-resolution screens.
Googling led me to this question. Would it be possible to run python in
<key>NSHighResolutionCapable</key>
<true/>
mode? If I understand correctly this should shrink the window by a factor of 2, but then produce the sharp image. If this succeeds, one may simply double the figure dpi in matplotlib and possibly use larger images for the buttons in the tk backend.
I have been using this patch for years on GNU/Linux with X.org to get correct DPI scaling:
--- a/lib/matplotlib/backends/_backend_tk.py
+++ b/lib/matplotlib/backends/_backend_tk.py
@@ -212,6 +212,10 @@ class FigureCanvasTk(FigureCanvasBase):
self._tkcanvas.focus_set()
+ # set correct DPI scaling
+ factor = self._tkcanvas.winfo_fpixels('1i') / 96
+ self.figure.dpi *= factor
+
def _update_device_pixel_ratio(self, event=None):
# Tk gives scaling with respect to 72 DPI, but Windows screens are
# scaled vs 96 dpi, and pixel ratio settings are given in whole
It would be good if matplotlib did this out-of-the-box, so I can avoid always recompiling the package.
Why do you expect that this won't be acceptable? It seems reasonable, is there something I am missing? It looks like rather than expecting an API to give us the ratio, we ask tk how many pixels an inch is and compute it our selves?
Nothing in particular, I just don't know what is the intended behaviour regarding DPI scaling and if my change needs to respect some settings.
As is, this will always rescale the figure and UI, probably overriding rcParams['figure.dpi'], but I haven't tested.
It looks like rather than expecting an API to give us the ratio, we ask tk how many pixels an inch is and compute it our selves?
I'm not sure what code I was looking at / remembering. Sorry for pointing you in the wrong direction. There is some subtley with dealing with hidpi as we want to update the dpi when rendering to the screen but not when saving so just directly updating the dpi in __init__ is not correct.
Activity
tacaswell commentedon Feb 7, 2018
@evgenyneu Does tk provide an API to opt into hi-dpi support?
evgenyneu commentedon Feb 7, 2018
@tacaswell good question, I have not found must information on this, apart from this option, not sure if it can help:
tacaswell commentedon Feb 7, 2018
That does look promising!
Want to take a crack at this? Looking at how we do this in the Qt backend is probably a good starting place.
evgenyneu commentedon Feb 7, 2018
Thanks, I'll see what I can do :)
evgenyneu commentedon Feb 7, 2018
I could not find a way to show an image that is appropriately scaled on retina screen. Here is a demo app shows shows a gif image. The code
root.tk.call('tk', 'scaling', 2.0)does not seem to do anything.evgenyneu commentedon Feb 7, 2018
It looks like a tkinter issue/feature. I could not find a way to detect current screen scaling (2x on my screen) and then apply this when showing an image. Does anyone know where can I find people who maintain tkinter to report this?
efiring commentedon Feb 7, 2018
I did a little googling and came up with nothing promising. From my reading, the 'scaling' parameter has little or nothing to do with retina support. What is happening now is that our Tkagg backend is seeing the retina display only in its pixel-doubled compatibility mode.
Gitk now looks nice and sharp on my retina display, though, including the history graph lines, which suggests that use of full resolution is not impossible. Gitk is using a Perl interface to Tk, I believe.
Tkinter is part of the regular python installation, but I haven't found any sign of a dedicated maintainer for it. Even the link to the tkinter wiki is now dead.
reaCodes commentedon Feb 7, 2018
My computer system is Windows 10, 1709 .


The resolution is 2560*1440, DPI Zoom is 200%
I encounter a similar situation.
I encountered a similar situation
When I delete
matplotlib.use('TkAgg')The display is still vague,
The UI looks hazy on high-resolution screens.
tacaswell commentedon Feb 7, 2018
@reaCodes It looks like it is using 'tkagg' anyway (check
matplotlib.get_backend())reaCodes commentedon Feb 8, 2018
@tacaswell

ImportanceOfBeingErnest commentedon Feb 8, 2018
Googling led me to this question. Would it be possible to run python in
mode? If I understand correctly this should shrink the window by a factor of 2, but then produce the sharp image. If this succeeds, one may simply double the figure dpi in matplotlib and possibly use larger images for the buttons in the tk backend.
tacaswell commentedon Feb 8, 2018
@ImportanceOfBeingErnest That is exactly how we do it for Qt (transparently double the DPI for rendering to the screen and using bigger icons).
12 remaining items
rnhmjoj commentedon Jun 10, 2024
I have been using this patch for years on GNU/Linux with X.org to get correct DPI scaling:
It would be good if matplotlib did this out-of-the-box, so I can avoid always recompiling the package.
tacaswell commentedon Jun 10, 2024
@rnhmjoj Could you open a PR with that patch?
attn @richardsheridan
rnhmjoj commentedon Jun 12, 2024
I'm not sure if the matplotlib developers would consider this acceptable. I posted it here to receive some comments before making a serious attempt.
tacaswell commentedon Jun 12, 2024
Why do you expect that this won't be acceptable? It seems reasonable, is there something I am missing? It looks like rather than expecting an API to give us the ratio, we ask tk how many pixels an inch is and compute it our selves?
rnhmjoj commentedon Jun 12, 2024
Nothing in particular, I just don't know what is the intended behaviour regarding DPI scaling and if my change needs to respect some settings.
As is, this will always rescale the figure and UI, probably overriding rcParams['figure.dpi'], but I haven't tested.
Yes, at least that's how I understand it.
tacaswell commentedon Jun 12, 2024
oh, I see I read too fast. We have a
_dpi_scaleattribute which is what should be set instead.rnhmjoj commentedon Jul 14, 2024
Cam you point it to me? I can't find a reference to
_dpi_scaleanywhere in the code.tacaswell commentedon Jul 16, 2024
I'm not sure what code I was looking at / remembering. Sorry for pointing you in the wrong direction. There is some subtley with dealing with hidpi as we want to update the dpi when rendering to the screen but not when saving so just directly updating the dpi in
__init__is not correct.However, we already have
matplotlib/lib/matplotlib/backends/_backend_tk.py
Lines 236 to 246 in 9b8a8c7
which get auto-called on windows via
matplotlib/lib/matplotlib/backends/_backend_tk.py
Lines 179 to 180 in 9b8a8c7
I suspect the correct implementation is to always call
_update_device_pixel_ratioand to put the non-win32 method of getting the scaling ratio in it.rnhmjoj commentedon Aug 22, 2024
If anyone feels like it, I made a PR to try to fix this: #28588
QuLogic commentedon Sep 21, 2024
Unfortunately, #28588 only applied to Linux, so this is not yet fixed.