In linux, copying a tkinter font doubles its size when using Tk 8.6 and a hi-res screen. #128719
Description
Bug report
Bug description:
>>> import tkinter
>>> from tkinter.font import Font
>>> root = tkinter.Tk()
>>> f1 = Font(name='TkDefaultFont', exists=True)
>>> f1.actual()
{'family': 'Noto Sans', 'size': 20, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0}
>>> f2 = f1.copy()
>>> f2.actual()
{'family': 'Noto Sans', 'size': 40, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0}
>>> f3 = f2.copy()
>>> f3.actual()
{'family': 'Noto Sans', 'size': 80, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0}
>>> f4 = f3.copy()
>>> f4.actual()
{'family': 'Noto Sans', 'size': 160, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0}The example above is from Ubuntu 24.04 running on an Asus Zenbook with EVO screen. The display scaling from the system settings is the default, namely 200%. This does not happen when the display scaling is 100%.
Note that font f1 is already (more than) doubled in size, compared to what wish8.6 (built from 8.6.15 source) reports:
% info patchlevel
8.6.15
% font actual TkDefaultFont
-family {Noto Sans} -size 9 -weight normal -slant roman -underline 0 -overstrike 0
% font config TkDefaultFont
-family sans-serif -size -12 -weight normal -slant roman -underline 0 -overstrike 0
The negative value -12 means that the size is 12 pixels, as opposed to 12 points. I think the intitial expansion being slightly more than a factor of 2 may be caused by rounding when converting pixels to points.
Note that the behavior of Tk 9 is different. Using wish9.0 on the same system produces:
% info patchlevel
9.0.0
% font actual TkDefaultFont
-family {Noto Sans} -size 10 -weight normal -slant roman -underline 0 -overstrike 0
% font config TkDefaultFont
-family sans-serif -size 10 -weight normal -slant roman -underline 0 -overstrike 0
Also, the pending new version of tkinter from #124156 does not have this doubling behavior when used with Tk 9.0. (I have not tested the new tkinter with Tk 8.6, but I expect it to have the broken behavior since I don't think that the PR changes Font.copy.)
CPython versions tested on:
3.12
Operating systems tested on:
Linux
Activity
NathanDunfield commentedon Jan 11, 2025
I think the doubling behavior is because tkinter's
Font.copyrelies onFont.actual:On a high-res Linux screen with Ubuntu 24.04, the
sizeandself.actual()['size']differ, apparently by the scaling factor:This seems consistent with the Tk docs which say that
font actual:NathanDunfield commentedon Jan 11, 2025
Also, on stock Ubuntu 24.04, I see a very different result from @culler's built-from-source Tk 8.6:
Note everything here is in points, not a mix of points and pixels. The same difference between config and actual shows up in user-defined fonts:
culler commentedon Jan 11, 2025
This is probably a difference between 8.6.14 and 8.6.15. There is now a release of 8.6.16. I will report if it differs from 8.6.15.
NathanDunfield commentedon Jan 11, 2025
@culler: I think this Tk ticket is related.
culler commentedon Jan 11, 2025
Indeed! It looks like they ended up fixing a related Tk bug but never got to the tkinter issue raised in the original report, which seems to be the same as this one..
NathanDunfield commentedon Jan 11, 2025
I installed the proposed Ubuntu package
libtk 8.6.16-1by downloading the binary from launchpad. Now I get:NathanDunfield commentedon Jan 11, 2025
I'm thinking maybe there's nothing to do here for
tkinter. I suspect it would have been a better design to haveFont.copy()invokeconfiginstead ofactualas this seems like a poor copy:However, if Tk itself is working right, they should always display the same. Moreover,
Font.__init__invokesactualwhich is why one sees:whereas
wishwould saysans-serif. But presumably changing fromactualtoconfigwould cause minor havoc and be more trouble than it's worth.serhiy-storchaka commentedon Jun 27, 2026
This was a Tk bug in
font actualon HiDPI displays — the resolved size was scaled relative to the configured size — and it was fixed upstream in Tk 8.6.16.As confirmed earlier in this thread, 8.6.16 makes
font actualagree withfont config, soFont.copy()(which snapshots viaactual()) no longer doubles the size. I re-verified on Tk 9.0.4 withtk scaling ≈ 2.0:configandactualboth report size 10, and a repeated.copy()chain stays at 10.The fix is in Tk, not tkinter, and all current Tk releases (8.6.16+, 9.0) include it, so I'm closing this as resolved upstream. Please upgrade Tk to 8.6.16 or later.