How to scale my Tkinter program across different PPIs and screen resolutions

901 Views Asked by At

I have been developing an app for someone and we quickly realized that the app looks different between our laptops (and on my tablet its un-usable because of the ppi). I looked up what the problem was so I used starting_frame.tk.call('tk', 'scaling', factor) to normalize the PPI across all devices. What I quickly realized, however, was the program will still be too big or too small depending on the screen ( i have a resolution set at root.geometry("1280x960") . In order to combat all of these problems, I created the code below:

root = tk.Tk()
dpi = root.winfo_fpixels('1i')
factor = dpi / 72

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


ratio_1 = width * height
ratio_2 = 1
r2_width = 4
r2_height = 3

while (ratio_1 / ratio_2) != 1.6875:
   r2_height = r2_width / 1.33333333333
   ratio_2 = r2_width * r2_height
   r2_width = r2_width + 1

   if (ratio_1/ratio_2) <= 1.6875:
       break
   if width + 1 == r2_width:
       break

root.geometry(str(r2_width) + "x"+ str(int(r2_height)))

starting_frame = tk.Canvas(root)

factor_multiplier = (.40*factor) +.46
factor = factor/factor_multiplier

starting_frame.tk.call('tk', 'scaling', factor)
starting_frame.place(height=int(r2_height), width = r2_width)

Let me break this down:

dpi = root.winfo_fpixels('1i')
factor = dpi / 72

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

this just grabs the ppi of the device and the screen res....

ratio_1 = width * height
ratio_2 = 1
r2_width = 4
r2_height = 3

while (ratio_1 / ratio_2) != 1.6875:
    r2_height = r2_width / 1.33333333333
    ratio_2 = r2_width * r2_height
    r2_width = r2_width + 1

    if (ratio_1/ratio_2) <= 1.6875:
        break
    if width + 1 == r2_width:
        break

root.geometry(str(r2_width) + "x"+ str(int(r2_height)))

This basically takes my 16x9 display and finds a 4:3 resolution that is 88% or so the area of my screen res (i just think its a good size and is that my program is based around).

factor_multiplier = (.40*factor) +.46
factor = factor/factor_multiplier

this converts the ppi of any screen so that the size of the text and stuff is normalized across displays (I assumed a linear relation).

starting_frame.tk.call('tk', 'scaling', factor)
starting_frame.place(height=int(r2_height), width = r2_width)

this is just making a frame and stuff based on my calculated new ppi and res.

While this sorta works, and then all of my hard coded text positions are multiplied by my factor_multiplier , it is a very sloppy and long way of doing this. please tell me there is a better way because I have been looking and I can't find anything that suits my needs.

1

There are 1 best solutions below

0
On

You can the ctypes Python library. This following setting in the ctypes library sets DPI awareness.

import ctypes
 
ctypes.windll.shcore.SetProcessDpiAwareness(1)