TomSchimansky / CustomTkinter

A modern and customizable python UI-library based on Tkinter
MIT License
11.63k stars 1.09k forks source link

[BUG] CustomTkInter renders incorrectly on Linux when desktop scaling is used. #2597

Open Arcitec opened 2 months ago

Arcitec commented 2 months ago

System:

I have seen this bug in a lot of tickets here. Many people might not realize what's wrong.

The issue is that CustomTkInter renders all controls and their borders in a squashed way when desktop UI scaling is used:

Here, my desktop is set to 200% scale:

image

This is how CustomTkInter renders (buggy) at 200%:

image

This is how it renders (correctly) when I set the desktop to 100%:

image

To support desktop scaling, it looks like the issue is that CustomTkInter needs to detect the desktop scale and enlarge its own widgets to fit everything correctly. Right now, it seems like the widgets at 200% are rendering with larger widgets but within the exact same PHYSICAL space as 100% widgets would use.

dipeshSam commented 2 months ago

Did you try it with scaling manually? For example:

from customtkinter import CTk, CTkLabel
from customtkinter import set_window_scaling, set_widget_scaling

if __name__ == "__main__":
    app = CTk()
    app.geometry("500x300")

    set_window_scaling(2)  # 2 for 200% scaling.
    set_widget_scaling(2)

    lab = CTkLabel(app, text="Sample Text", fg_color="darkblue", corner_radius=10)
    lab.place(relx=0.5, anchor="center", rely=0.5)

    app.mainloop()

Regards

Arcitec commented 2 months ago

@dipeshSam Thanks for the suggestion. I tried it now, but it made things worse. CustomTkInter is clearly scaling to 200% from my desktop settings. And with your change, it's also scaling to +200% inside its own GUI. This means with your suggested changes, I now have a total of 400% GUI scaling. So everything is now bigger, but the widgets are still broken in the exact same way as before. :rofl:

This means that CustomTkInter's widget rendering itself is broken on high desktop scaling on Linux (at least on GNOME, I don't have KDE to test).

image

dipeshSam commented 2 months ago

Oh! @TomSchimansky should take a look into this matter.

ghost commented 2 months ago

You can call xdpyinfo from linux with subprocess to check the scale. Next step is to make a function to calculate the scale factor and one more which will update all widgets.


import subprocess
import customtkinter as ctk

def scaling_info():
    output = subprocess.check_output("xdpyinfo | grep dots", shell=True).decode("utf-8")
    dpi = int(output.split()[1].split('x')[0])
    scaling_factor = dpi / 96.0
    return scaling_factor

app = ctk.CTk()
app.geometry("500x400")

scaling_factor = scaling_info()

def update_all_widgets_scaling():
    for widget in app.winfo_children():
        if isinstance(widget, ctk.CTkButton):
            widget.configure(width=int(150 * scaling_factor), height=int(50 * scaling_factor))

        elif isinstance(widget, ctk.CTkLabel):
            widget.configure(font=("Arial", int(14 * scaling_factor)))

    app.update()

label = ctk.CTkLabel(app, text=f"Scale DPI factor: {scaling_factor:.2f}")
label.pack(pady=20)
button = ctk.CTkButton(app, text="Button 1")
button.pack(pady=10)

button2 = ctk.CTkButton(app, text="Button 2")
button2.pack(pady=10)

label2 = ctk.CTkLabel(app, text="label")
label2.pack(pady=10)
update_all_widgets_scaling()

app.mainloop()
hacker-3342 commented 2 months ago

I do have the same issue on the KDE Plasma version of fedora 40 workstation. I’ll try to switch to Gnome and try it on my machine. Thanks!

Arcitec commented 2 months ago

You can call xdpyinfo from linux with subprocess to check the scale. Next step is to make a function to calculate the scale factor and one more which will update all widgets.

Thanks @mst4ck for the suggestion and code. I tried it and it did not work, unfortunately:

My desktop at 200% scale shows this broken rendering as usual:

image

My desktop at 100% scale shows this correct rendering:

image

So yeah that's full confirmation that CustomTkInter's scaling is bugged on Linux.

@hacker-3342

I do have the same issue on the KDE Plasma version of fedora 40 workstation. I’ll try to switch to Gnome and try it on my machine. Thanks!

Don't bother trying GNOME. I am on GNOME and it's bugged there too. But thank you for confirming that KDE Is broken too so I don't have to wonder about it. :)

Arcitec commented 2 months ago

And yeah X11 scaling is saying the same thing no matter what the GNOME monitor scaling is set to (ran with 200% and 100% desktop scaling here):

image

This makes sense because those deprecated APIs are not used anymore. Scaling uses something else nowadays, and is probably window manager-specific (GNOME vs KDE vs Hyprland etc).

ghost commented 2 months ago

You can try another thing to check the scale factor in gnome. Maybe will work now:)


def dpi_scale_info():
    dpi_scale = int(os.environ.get('GDK_SCALE', 1))
    dpi_dpi_scale = float(os.environ.get('GDK_DPI_SCALE', 1))
    dpi_factor = dpi_scale * dpi_dpi_scale
    return dpi_factor