我希望我的应用程序能够检测它是否在HiDPI屏幕上运行,如果是,请自行调整以便可用。如this question所述,我知道我需要设置一个比例因子,这个因素应该是我的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屏幕上运行良好,并且在正常情况下也可以正常工作?谢谢!
答案 0 :(得分:3)
此答案来自此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厘米(as found here)上的像素数。 因此,要获得dpi,我们要求函数提供1英寸屏幕(“ 1i”)中的像素数。
答案 1 :(得分:0)
我使用的是TclTk,而不是TkInter,而我知道如何执行此操作的唯一方法是从字体指标中得出答案...
%字体指标Tk_DefaultFont -上升30-下降8-行距38-固定0
行距大约是DPI的0.2倍(此处当前设置为192)
答案 2 :(得分:0)
我知道我要晚回答这个问题,但是我想扩展@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()