经过几个小时的调整,我已经确定了这段代码,它允许我绕过熟悉的问题,即在使用Python 3中的Tkinter接口时,Windows 10中的高DPI显示上的模糊/模糊文本.

我不想设置兼容性标志,也不希望其他人这么做.我发现,通过DLL调用将DPI感知标记为"开启",然后检索DPI设置,我就可以在其中放大GUI窗口和框架.

然而,在将其传递给其他人之前,我想判断我将"GUI"(一个tkinter.Tk()实例)传递给主体中的MakeTkDPIAware函数并让该函数向其添加自定义属性的方法是否是一个健康的 Select ,或者是否会给tkinter实例带来问题.添加的属性可以在主体中使用,但可以安全地假设这种情况总是会发生吗?

我已经能够找出这种做法是否为人所知,是否被人反对或是一个糟糕的设计 Select .(在Python中,我经常会因为得到一些有用的东西而兴奋不已,以至于忘了判断这类问题),所以我希望有人能提供建议.这似乎是"记住"zoom 数据的最整洁的方式,而不是创建新的全局变量.

我很想知道另一种解决方案是否会更像Python .

import re


def Get_HWND_DPI(window_handle):
    #To detect high DPI displays and avoid need to set Windows compatibility flags
    import os
    if os.name == "nt":
        from ctypes import windll, pointer, wintypes
        try:
            windll.shcore.SetProcessDpiAwareness(1)
        except Exception:
            pass  # this will fail on Windows Server and maybe early Windows
        DPI100pc = 96  # DPI 96 is 100% scaling
        DPI_type = 0  # MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2
        winH = wintypes.HWND(window_handle)
        monitorhandle = windll.user32.MonitorFromWindow(winH, wintypes.DWORD(2))  # MONITOR_DEFAULTTONEAREST = 2
        X = wintypes.UINT()
        Y = wintypes.UINT()
        try:
            windll.shcore.GetDpiForMonitor(monitorhandle, DPI_type, pointer(X), pointer(Y))
            return X.value, Y.value, (X.value + Y.value) / (2 * DPI100pc)
        except Exception:
            return 96, 96, 1  # Assume standard Windows DPI & scaling
    else:
        return None, None, 1  # What to do for other OSs?


def TkGeometryScale(s, cvtfunc):
    patt = r"(?P<W>\d+)x(?P<H>\d+)\+(?P<X>\d+)\+(?P<Y>\d+)"  # format "WxH+X+Y"
    R = re.compile(patt).search(s)
    G = str(cvtfunc(R.group("W"))) + "x"
    G += str(cvtfunc(R.group("H"))) + "+"
    G += str(cvtfunc(R.group("X"))) + "+"
    G += str(cvtfunc(R.group("Y")))
    return G


def MakeTkDPIAware(TKGUI):
    TKGUI.DPI_X, TKGUI.DPI_Y, TKGUI.DPI_scaling = Get_HWND_DPI(TKGUI.winfo_id())
    TKGUI.TkScale = lambda v: int(float(v) * TKGUI.DPI_scaling)
    TKGUI.TkGeometryScale = lambda s: TkGeometryScale(s, TKGUI.TkScale)


#Example use:
import tkinter


GUI = tkinter.Tk()
MakeTkDPIAware(GUI)  # Sets the windows flag + gets adds .DPI_scaling property
GUI.geometry(GUI.TkGeometryScale("600x200+200+100"))
gray = "#cccccc"
DemoFrame = tkinter.Frame(GUI, width=GUI.TkScale(580), height=GUI.TkScale(180), background=gray)
DemoFrame.place(x=GUI.TkScale(10), y=GUI.TkScale(10))
DemoFrame.pack_propagate(False)
LabelText = "Scale = " + str(GUI.DPI_scaling)
DemoLabel = tkinter.Label(DemoFrame, text=LabelText, width=10, height=1)
DemoLabel.pack(pady=GUI.TkScale(70))

推荐答案

简单地使用

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

允许字体大小调整解决了我在Windows 10上的问题.

不知道为什么没有人 comments 或帮助.字体模糊是一件痛苦的事,我希望这篇文章能引起争论,并为这个讨厌的Tkinter找到一个最好的解决方案..

Python-3.x相关问答推荐

如何在Python Matplotlib中在x轴上放置点

替换Pandas中组下的列值

Numpy argmin()以查找最近的元组

如何在输入正确的用户名和密码时添加按钮?

根据第一个字典的值序列对第二个字典进行排序

为什么 tkinter 在 tkinter 窗口外计算鼠标事件?

从列表的元素和python中的多个多索引数据帧执行方程

如何使用复选按钮更改 Pyplot 轴的属性?

使用 selenium 加速网页抓取

如何将虚拟变量列转换为多列?

判断是否存在大文件而不下载它

为什么 f-strings 比 str() 更快地解析值?

活动屏幕上的 PyQt4 中心窗口

django - 值更改后自动更新日期

Linux Mint 上的 Python3 错误没有名为蓝牙的模块

如何使用 asyncio 添加连接超时?

从大字典中弹出 N 项的最快方法

用于 unicode 大写单词的 Python 正则表达式

Python 3.4 多处理队列比 Pipe 快,出乎意料

在 Keras 中训练神经网络的零精度