python 3.x official Tentativo di risolvere il testo tkinter sfocato+ridimensionamento su schermi DPI alti di Windows 10, ma il mio approccio non è Pythonic o non è sicuro



tkinter example (1)

Semplicemente usando windll.shcore.SetProcessDpiAwareness(1) e consentendo la modifica della dimensione del carattere risolto i miei problemi su Windows 10.

Non so perché nessuno ha commentato o assistito però. I caratteri sfocati sono un dolore, mi aspetto che questo thread abbia un dibattito e una soluzione migliore per questo fastidio di Tkinter.

Dopo ore di perfezionamento, ho optato per questo codice che mi consente di aggirare il familiare problema del testo sfocato / sfocato in Windows 10 su schermi ad alta risoluzione DPI quando si utilizzano le interfacce Tkinter in Python 3.

Non volevo dover impostare il flag di compatibilità o aspettarmi che gli altri lo facessero e ho scoperto che contrassegnando la consapevolezza DPI 'on' attraverso una chiamata DLL e quindi recuperando l'impostazione DPI, avrei potuto ridimensionare la finestra GUI e i frame all'interno .

Prima di passare questo ad altri, tuttavia, volevo controllare se il mio approccio di passare 'GUI' (un'istanza tkinter.Tk ()) alla funzione MakeTkDPIAware nel corpo principale e ottenere quella funzione per aggiungere proprietà personalizzate ad esso fosse un scelta o rischia di causare problemi all'istanza di tkinter. Le proprietà aggiunte sono quindi disponibili per l'uso nel corpo principale, ma è lecito ritenere che accadrà sempre?

Sono stato in grado di scoprire se questa pratica è nota - e se è disapprovata o una scelta di design scarsa. (Così spesso in Python, posso essere così entusiasta di ottenere qualcosa che funzioni che ho dimenticato di controllare questo tipo di domande in quel momento), quindi spero che qualcuno possa consigliarlo. Sembrava il modo più semplice per "ricordare" i dati di ridimensionamento, piuttosto che creare una nuova variabile globale.

Sarei molto interessato a sapere se un'altra soluzione sarebbe più Pythonic.

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))




windows-10