tkinter 中的字体大小与 window 大小/像素密度因子/Tkinter 中的原始屏幕分辨率之间的关系是什么

What is the relation between font size in tkinter and window size/ pixel density factor/ original screen resolution in Tkinter

这个问题让我很困惑,我似乎无法弄清楚为什么它不能按设备正确缩放。

我在 3 台不同的计算机(2 台笔记本电脑和一台 android 平板电脑)上有 运行 我的代码,但我不明白发生了什么。

我也在使用比例因子 (dpi/72)。显示的是原始比例因子,但我使用以下代码使比例因子与我的主要笔记本电脑比例因子成比例:[​​=14=]

dpi = root.winfo_fpixels('1i')
factor = dpi / 72
factor_multiplier = (.40*factor) +.46
factor = factor/factor_multiplier
starting_frame.tk.call('tk', 'scaling', factor)

主机:

屏幕尺寸:1920x1980,window尺寸:1280x960,比例因子:1.3,正确字体:40

其他:

屏幕尺寸:1366x768,window尺寸:1912x683,比例因子:1.3,正确字体:30

屏幕尺寸:2560x1600,window尺寸:1750x1311,比例因子:5.7,正确字体:30

每个window尺寸大约是实际屏幕分辨率的88%,换算成4:3大概。

我不明白我的另外两台笔记本电脑怎么会有如此不同的屏幕分辨率 + dpi 但仍然需要相同的字体大小。 dpi 也与我的主要笔记本电脑成比例,所以这可能是一个因素,因为 well.All 字体“适合”window,它们并不都适合按比例制作的盒子(即盒子对于所有屏幕分辨率,比例相同,如下面的完整相关代码所示。

相关代码是这样的:

def font_size_calc(): #this is the problematic code that isnt scaling the font size right
    global r2_width, r2_height
    x = r2_width*int(r2_height)
    return str(math.ceil((-(1/106545)*x) + 51.533155004927)) #linear equation I made, slope = fontsize/screen's area
    '''
    I tried creating a linear equation based on the fonts that worked for
    2 of my devices, but a device with a smaller screen resolution than both of my devices needs a font size of 30 like my highest res device
    to have the words stay in the box
    '''
starting_frame.create_text(adjusted_pixels(2,"x"),adjusted_pixels(2.742857,"y"),
    text = "Enter number of laps",fill = "gray", font=("Calibri "+ font_size_calc())) #calls font_size_calc() to get a working font size
    #I want the text to fit in the box created by the var border, it works on my laptop and tablet, but not another old laptop with a smaller screen res
    #obviously my equation is wrong but im not sure how to scale the font to work in all cases

程序代码(已编辑以便您也可以 运行):

import tkinter as tk
from tkinter.ttk import *
import math
from PIL import ImageTk,Image

root = tk.Tk()
dpi = root.winfo_fpixels('1i')
factor = dpi / 72 #gets how many times biger the dpi is than the standard 72, used for making the screen widgets proportional later
width = root.winfo_screenwidth()
height = root.winfo_screenheight()


ratio_1 = width * height
ratio_2 = 1 #init
r2_width = 4 #setting the window to a 4/3 resolution
r2_height = 3

while (ratio_1 / ratio_2) != 1.6875: #making sure that the new window is 88% the area of the old window
    r2_height = r2_width / 1.333333333333333333333333333333333333333333333333333333 #gets hieght
    ratio_2 = r2_width * r2_height # gets the area of the new screen size
    r2_width = r2_width + 1 #increases the width by one

    if (ratio_1/ratio_2) <= 1.6875: #makes sure it doesnt go too far over
        break
    if width + 1 == r2_width: #another check to make sure it doesnt keep going
        break

print("{} x {} = {}".format(str(r2_width),str(r2_height),str(ratio_1/ratio_2)))#prints your ending resolution to manually check accuracy

root.geometry(str(r2_width) + "x"+ str(int(r2_height))) #sets window resolution
starting_frame = tk.Canvas(root) #makes a frame

factor_multiplier = (.40*factor) +.46 #makes a multiplier based on an equation I cam up with (im so glad it was linear)
factor = factor/factor_multiplier #sets factor to be this new peoportion
starting_frame.tk.call('tk', 'scaling', factor)#adjusts tkinter scaling factor for the pixels
starting_frame.place(height=int(r2_height), width = r2_width) #places the frame




images = []
def create_rectangle(frame, x1, y1, x2, y2, **kwargs): #this works so dont worry about this function
    if 'alpha' in kwargs:
        alpha = int(kwargs.pop('alpha') * 255)
        fill = kwargs.pop('fill')
        fill = root.winfo_rgb(fill) + (alpha,)
        image = Image.new('RGBA', (x2-x1, y2-y1), fill)
        images.append(ImageTk.PhotoImage(image))
        frame.create_image(x1, y1, image=images[-1], anchor='nw')
    return frame.create_rectangle(x1, y1, x2, y2, **kwargs)

def adjusted_pixels(number, x_or_y): #this code creates new coordinates based on set numbers I ahve already made and works aswell
    global r2_width, r2_height

    if x_or_y == 'x':
        print(int(r2_width / number))
        return(int(r2_width / number))
    else:
        print(int(r2_height / number))
        return(int(r2_height / number))

def font_size_calc(): #this is the problematic code that isnt scaling the font size right
    global r2_width, r2_height
    x = r2_width*int(r2_height)
    return str(math.ceil((-(1/106545)*x) + 51.533155004927)) #linear equation I made, slope = fontsize/screen's area
    '''
    I tried creating a linear equation based on the fonts that worked for
    2 of my devices, but a device with a smaller screen resolution than both of my devices needs a font size of 30 like my highest res device
    to have the words stay in the box
    '''


boarder = create_rectangle(starting_frame,adjusted_pixels(3.368421,"x"), adjusted_pixels(3.2,'y'),
    adjusted_pixels(1.4222222,"x"), adjusted_pixels(1.45454545,"y"), fill='black',alpha = .78,outline = "red") #creates a box thats slightly transparent, works fine
lap_text = starting_frame.create_text(adjusted_pixels(2,"x"),adjusted_pixels(2.742857,"y"),
    text = "Enter number of laps",fill = "gray", font=("Calibri "+ font_size_calc())) #calls font_size_calc() to get a working font size
    #I want the text to fit in the box created by the var border, it works on my laptop and tablet, but not another old laptop with a smaller screen res
    #obviously my equation is wrong but im not sure how to scale the font to work in all cases

root.mainloop()

您可能想知道为什么我要弄乱比例因子 (dpi/72) 而不是将其设为 1。我碰巧喜欢我的程序在我的笔记本电脑上的显示方式并且我希望它按比例每个设备都一样,这就是我搞砸它的原因。

同样,我似乎无法根据分辨率缩放字体大小,我不确定为什么屏幕分辨率较低(与主笔记本电脑的 dpi 相同)和屏幕分辨率较高(与我的主笔记本电脑不同的 dpi)都需要相同的字体大小,但我的主笔记本电脑需要不同的字体。

我的问题是:我是根据屏幕 window 而不是全屏大小计算字体。这是我得到的尺码不正确。