CustomTkinter icon indicating copy to clipboard operation
CustomTkinter copied to clipboard

Center Window (get screensize independent of scaling)

Open matypoker opened this issue 2 years ago • 27 comments

there is a way to init the window or toplevel in the center of the screen? no matter the scale? using eval method and (width//2, height//2) does not work. I don't found a similar question using customtkinter on google.

matypoker avatar Jun 11 '23 13:06 matypoker

i could use a tk window, but antialiasing is awful

matypoker avatar Jun 11 '23 13:06 matypoker

@matypoker Try this method:

import customtkinter as ctk

root = ctk.CTk()

width = 500
height = 500
spawn_x = int((root.winfo_screenwidth()-width)/2) 
spawn_y = int((root.winfo_screenheight()-height)/2)

root.geometry(f"{width}x{height}+{spawn_x}+{spawn_y}")

root.mainloop()

Akascape avatar Jun 11 '23 18:06 Akascape

@matypoker Try this method:

import customtkinter as ctk

root = ctk.CTk()

width = 500
height = 500
spawn_x = int((root.winfo_screenwidth()-width)/2) 
spawn_y = int((root.winfo_screenheight()-height)/2)

root.geometry(f"{width}x{height}+{spawn_x}+{spawn_y}")

root.mainloop()

nop, don't work test

matypoker avatar Jun 11 '23 19:06 matypoker

@matypoker but it is working on my system (windows11). It can be an environment issue.

Akascape avatar Jun 12 '23 09:06 Akascape

mmm, do you think its windows or vscode?

matypoker avatar Jun 12 '23 17:06 matypoker

when I use a TK window all methods work fine.

matypoker avatar Jun 12 '23 17:06 matypoker

@matypoker Try to run in the native compiler (that comes with python) instead of VSCode.

Akascape avatar Jun 12 '23 18:06 Akascape

It appears centrally on my screen (Pycharm on Linux Mint): image

avalon60 avatar Jun 12 '23 19:06 avalon60

test

well, i make it run with python terminal and the problem still... :_(

matypoker avatar Jun 12 '23 21:06 matypoker

I want to clarify that I took drastic measures and formatted the PC. The last image I sent is after the formatting, and I only installed Python and VS Code. It's Windows 11

matypoker avatar Jun 12 '23 22:06 matypoker

I found the problem, it's the Windows scaling. I reduced the scaling to 100% and it works fine. When I disable the automatic scaling and go back to my Windows scaling, the image quality is terrible. Just as the CTk documentation says.

matypoker avatar Jun 12 '23 23:06 matypoker

"winfo_screenwidth" returns the screen values with scaling applied, not the actual values. For example, if the resolution of my screen is 3840x2160 with a scaling of 175%, the value returned by "winfo_screenwidth" and "winfo_screenheight" would be 2194x1234. Is there any way to access the actual resolution without scaling?

matypoker avatar Jun 13 '23 00:06 matypoker

@matypoker in that case we can also adjust the scalling for the CTk window.

Akascape avatar Jun 13 '23 04:06 Akascape

I'm not sure how to implement customtkinter.set_widget_scaling(float_value) and customtkinter.set_window_scaling(float_value). It has to be done for every scale automatically.

What I'm saying is that each PC will have a different scale, and the window has to start centered regardless of the scale.

matypoker avatar Jun 13 '23 16:06 matypoker

@matypoker Maybe disabling the scaling can work.

import ctypes
ctypes.windll.shcore.SetProcessDpiAwareness(0)

Akascape avatar Jun 13 '23 17:06 Akascape

For future questions, I would suggest creating questions in Discussions (specifically the Q&A section).

Maybe this would work? :

  1. Get the user's current UI scale (not sure how this would be accomplished)
  2. Disable the scaling as @Akascape said here
  3. Center the window with the solution @Akascape provided here
  4. Finally re-enable UI scaling with .set_widget_scaling() and .set_window_scaling()

You may also have to re-enable the system UI scaling (basically the reverse of ctypes.windll.shcore.SetProcessDpiAwareness(0)).

ghost avatar Jun 13 '23 23:06 ghost

Disable scaling and center the window, but scaling cannot be reactivated once the window is created. I suppose scaling can be reactivated with:

customtkinter.set_widget_scaling(float_value) # widget dimensions and text size customtkinter.set_window_scaling(float_value) # window geometry dimensions

However, I don't quite understand the values I should assign to float_value, or how to obtain the scaling and pass it to the function.

matypoker avatar Jun 14 '23 22:06 matypoker

However, I don't quite understand the values I should assign to float_value, or how to obtain > the scaling and pass it to the function.

I can help you with this @matypoker:

0.8 = 80% of UI scale (smaller) 1.0 = 100% of UI scale (original) 1.1 = 110% of UI scale (bigger)

ghost avatar Jun 14 '23 23:06 ghost

I will overwrite winfo_screenwidth and winfo_screenheight soon to return the unscaled values so that the approach at the beginning will work independent of the Windows scaling.

TomSchimansky avatar Jun 15 '23 08:06 TomSchimansky

you can get the proper resolution like so:

import ctypes

scaleFactor = ctypes.windll.shcore.GetScaleFactorForDevice(0)/100

root = customtkinter.CTk()

w, h = int(root.winfo_screenwidth()*scaleFactor), int(root.winfo_screenheight()*scaleFactor)

My problem is that root.attributes("-fullscreen", True) does not go fullscreen, probably because ctk gets the wrong resolution because of the scaling.

brurpo avatar Jul 07 '23 15:07 brurpo

Maybe disable scaling effects on ctk, make the window full screen, then enable scaling?

ghost avatar Jul 07 '23 20:07 ghost

Maybe disable scaling effects on ctk, make the window full screen, then enable scaling?

Once the window instance is created. Enabling or disabling scaling not has effect

matypoker avatar Jul 07 '23 22:07 matypoker

Hey, I managed to get into proper full screen, and exiting, by doing so:

root.state('zoomed')
root.attributes("-fullscreen", True)

root.state('normal')
root.attributes("-fullscreen", False)

ctk was able to enter proper full screen when the window was maximized, but only "maximized" to 1/4 of the screen when not. (scaling 200%)

brurpo avatar Jul 07 '23 22:07 brurpo

What you can do is disable scaling, obtain the Windows scaling value using "customtkinter.ScalingTracker.get_window_dpi_scaling", and then manually apply scaling to all widgets, including font sizes. Start the window with the alpha attribute set to 0, and the window in its normal state without modifications. Then, using an "after" method, change the state to "fullscreen" and set the alpha back to 1. The delay for the "after" method can be as short as 25 milliseconds because, in my experience, if you start the window with altered states, it doesn't work correctly. However, if you do it after initialization, it works fine. Since the "alpha" is set to 0, the change won't be visible.

matypoker avatar Jul 07 '23 23:07 matypoker

While @matypoker's approach works, using the after function does take up a little bit of processing/CPU power. Not sure if it has any performance effects, but I don't think it is ideal.

ghost avatar Jul 07 '23 23:07 ghost

I didn't know, I use the after method for almost everything, and I never had performance issues.

matypoker avatar Jul 08 '23 17:07 matypoker

This will work properly

import customtkinter
import ctypes
scaleFactor = ctypes.windll.shcore.GetScaleFactorForDevice(0)/100

class App(customtkinter.CTk):
    def __init__(self, width, height):
        super().__init__()
        self.title("CTk example")
        screenwidth = self.winfo_screenwidth()
        screenheight = self.winfo_screenheight()
        geometry = '%dx%d+%d+%d' % (width, height, int((screenwidth - width) / 2*scaleFactor), int((screenheight - height) / 2*scaleFactor))
        self.geometry(geometry)
        self.button = customtkinter.CTkButton(self, command=self.button_click)
        self.button.grid(row=0, column=0, padx=20, pady=10)

    # add methods to app
    def button_click(self):
        print("button click")


app = App(500,200)
app.mainloop()

LiTao54826 avatar Feb 28 '24 14:02 LiTao54826