我希望我的应用程序能够检测它是否在 HiDPI 屏幕上运行,如果是,则扩展自身以使其可用。正如这个问题中所说,我知道我需要设置一个缩放因子,并且这个因子应该是我的DPI除以72;我的麻烦在于获取 DPI。这是我所拥有的:
def get_dpi(window):
MM_TO_IN = 1/25.4
pxw = window.master.winfo_screenwidth()
inw = window.master.winfo_screenmmwidth() * MM_TO_IN
return pxw/inw
root = Tk()
root.tk.call('tk', 'scaling', get_dpi(root)/72)
这不起作用(在我的 4k 笔记本电脑屏幕上测试)。经过进一步检查,我意识到
get_dpi()
返回的是 96.0,而 winfo_screenmmwidth()
返回的是 1016! (谢天谢地,我的笔记本电脑宽度不超过一米)。
我假设 TkInter 在这里根据一些内部检测到的 DPI 计算宽度(以毫米为单位),错误地检测为 96,但我不确定它从哪里得到这个;我目前使用的是 Linux,
xrdb -query
返回的 DPI 为 196,因此它无法从 X 服务器获取 DPI。
有谁知道一种跨平台的方法来获取我的屏幕 DPI,或者使 TkInter 能够正确获取它?或者,更重要的是:如何使 TkInter 在 HiDPI 屏幕上运行良好,并且在普通屏幕上也能正常工作?谢谢!
这个答案来自这个link,并作为上面的评论留下,但花了几个小时的搜索时间才找到。我还没有遇到任何问题,但如果它在您的系统上不起作用,请告诉我!
import tkinter
root = tkinter.Tk()
dpi = root.winfo_fpixels('1i')
相关文档说:
winfo_fpixels(number)
# Return the number of pixels for the given distance NUMBER (e.g. "3c") as float
距离数字是一个数字后跟一个单位,因此 3c 表示 3 厘米,该函数给出屏幕 3 厘米上的像素数(如此处所示)。 因此,为了获得 dpi,我们向函数询问 1 英寸屏幕(“1i”)中的像素数。
我知道我回答这个问题晚了,但我想扩展@Andrew Pye 的想法。你是对的,每当您使用“宽度”或“高度”或“pady”或任何以像素为单位测量的内容时,tkinter 的 GUI 在具有不同 DPI 的不同显示器上看起来都不同。当我在桌面上制作 GUI 时,我注意到了这一点,但后来在我的 4K 笔记本电脑上运行相同的 GUI(窗口和小部件在笔记本电脑上显得小得多)。这就是我修复它的方法,它对我有用。
from tkinter import *
ORIGINAL_DPI = 240.23645320197045 # This is the DPI of the computer you're making/testing the script on.
def get_dpi():
screen = Tk()
current_dpi = screen.winfo_fpixels('1i')
screen.destroy()
return current_dpi
SCALE = get_dpi()/ORIGINAL_DPI # Now this is the appropriate scale factor you were mentioning.
# Now every time you use a dimension in pixels, replace it with scaled(*pixel dimension*)
def scaled(original_width):
return round(original_width * SCALE)
if __name__ == '__main__':
root = Tk()
root.geometry(f'{scaled(500)}x{scaled(500)}') # This window now has the same size across all monitors. Notice that the scaled factor is one if the script is being run on a the same computer with ORIGINAL_DPI.
root.mainloop()
我使用的是 TclTk,而不是 TkInter,我知道如何做到这一点的唯一方法是根据字体指标来计算...
% 字体规格 Tk_DefaultFont -上升 30 -下降 8 -行间距 38 -固定 0
行距大约是 DPI 的 0.2 倍(当前设置为 192)
我是 Python 和 Tkinter 的新手,但这个解决方案适用于我的 4K 显示器上的任何类型的窗口大小。我希望它也对你有用:
import tkinter as tk
import customtkinter as ctk
from customtkinter import *
app = CTk()
screen_width = app.winfo_screenwidth()
screen_height = app.winfo_screenheight()
print("screen width = ", screen_width)
print("screen height = ", screen_height)
ratio_width = screen_width/3840
ratio_height = screen_height/2160
print("ratio width = ", ratio_width)
print("ratio height = ", ratio_height)
width_I_want = 1920
height_I_want = 1080
width = int(width_I_want*ratio_width)
height = int(height_I_want*ratio_height)
print("width = ", width)
print("height = ", height)
x = int((screen_width - width) /2/ratio_width)
y = int((screen_height - height) /2/ratio_height)
print("x = ", x)
print("y = ", y)
app.geometry(f"{width}x{height}+{x}+{y}")
set_appearance_mode("dark")
app.mainloop()