Search code examples
pythonpython-3.xmacostkinterscaling

Tkinter Python 3 scaling issue on MacOS


I am maintaining an application in Python3/Tkinter and add an issue opened by my first user on MacOS. This is the main screen on Windows in 1080p (Linux shows similar result) :

enter image description here

On MacOS in 2560 x 1600, everything in the UI is scaled approximatively with a 2x size :

enter image description here

The original code is that one :

self.window = Tk.Tk()
self.window.resizable(False,False)
if platform.system() == 'Windows' :
   self.window.iconbitmap('bestarcade.ico')
self.window.title(title)

I tried enforcing resolution :

self.scriptDir = scriptDir
self.window = Tk.Tk()
self.window.geometry("930x950")
self.window.resizable(False,False)

It makes things worse, the application window in MacOS is just cut a little more short

I tried scaling :

self.scriptDir = scriptDir
self.window = Tk.Tk()
self.window.tk.call('tk','scaling',0.5)
self.window.resizable(False,False)

And it doesn't change anything from the standard solution, as if it's not taken into account

Now from what I read, this seems to be Tkinter bug on MacOS, and the only solution I found require to hard set dimension for each fonts and UI components or something like that

Is there anything more simple I could try ?


Solution

  • So the solution, as @Bryan Oakley proposed, is juste to change the size of the default fonts on Mac OS. Now I wanted something user friendly, as I noticed the result on my macbook was also different from the one given by the user.

    I chose to use a Scale Tkinter component to allow the user to change the size of the font himself :

    EDIT : kept for the sake of the solution, but actually the Scale widget doesn't seem to be compatible with all MacOS version either, as it doesn't appear at all on some of them.

    First initialization of the GUI :

    class GUI():
    
    MACOS_DEFAULT_FONT_SIZE = 7
    DEFAULT_FONT_SIZE = 9      
    
    def __init__(self,scriptDir,logger,title) :        
        self.scriptDir = scriptDir
        
        self.window = Tk.Tk()
        self.window.resizable(False,False)        
        self.startFontSize = self.DEFAULT_FONT_SIZE        
        
        if platform.system() == 'Windows' :
            self.window.iconbitmap('bestarcade.ico')
        elif platform.system() == 'Darwin' :
            # Handle tkinter font size bug on MacOS
            self.startFontSize = self.MACOS_DEFAULT_FONT_SIZE
            
        self.setFontSize(self.startFontSize)
        self.window.title(title)        
        self.logger = logger
    
    def draw(self) :
        self.root = Tk.Frame(self.window,padx=10,pady=5)
        self.root.grid(column=0,row=0)
        self.drawSliderFrame()
        self.drawMainframe()
        self.window.mainloop()
    

    Then in the same class, creation of the scale component and its event handler (also used during initialization of the GUI) :

    def setFontSize(self, value) :        
        default_font = Font.nametofont("TkDefaultFont")
        default_font.configure(size=value)
        text_font = Font.nametofont("TkTextFont")
        text_font.configure(size=value)
        fixed_font = Font.nametofont("TkFixedFont")
        fixed_font.configure(size=value)
    
    def drawSliderFrame(self) :
        self.sliderFrame = Tk.Frame(self.root,padx=10,pady=0)
        self.sliderFrame.grid(column=0,row=0,sticky="EW",pady=0)
        self.sliderFrame.grid_columnconfigure(0, weight=1)
        self.slider = Tk.Scale(self.sliderFrame, from_=4, to=12, orient=Tk.HORIZONTAL, showvalue=0, command=self.setFontSize)
        wckToolTips.register(self.slider, 'Window Size') #TODO internationalization
        self.slider.grid(column=0,row=0,sticky="W",pady=0)
        self.slider.set(self.startFontSize)
    

    This seems to work well, although it does not resolve all issues around resolution and size of the screen Size of the windows might have to be reduced at little more than what is done automatically, too

    Here it is at default size (9) : enter image description here

    and here modified with the scale to size 7 : enter image description here