From a1afc3056becbe864fa9aae15f7f8079f04f0f6d Mon Sep 17 00:00:00 2001 From: Tom Schimansky Date: Thu, 26 May 2022 19:16:01 +0200 Subject: [PATCH] removed scaling with ctypes shcore for Windows < 8.1 --- customtkinter/__init__.py | 3 ++ customtkinter/scaling_tracker.py | 30 +++++++++--------- customtkinter/widgets/ctk_optionmenu.py | 31 ++++++++++++------- examples/simple_example.py | 3 -- setup.cfg | 2 +- .../manual_integration_tests/test_combobox.py | 8 +++-- 6 files changed, 45 insertions(+), 32 deletions(-) diff --git a/customtkinter/__init__.py b/customtkinter/__init__.py index c2d0186..20746ea 100644 --- a/customtkinter/__init__.py +++ b/customtkinter/__init__.py @@ -22,6 +22,9 @@ if sys.platform == "darwin": else: DrawEngine.preferred_drawing_method = "font_shapes" +if sys.platform.startswith("win") and sys.getwindowsversion().build < 9000: # No automatic scaling on Windows < 8.1 + ScalingTracker.deactivate_automatic_dpi_awareness = True + # load Roboto fonts (used on Windows/Linux) script_directory = os.path.dirname(os.path.abspath(__file__)) FontManager.load_font(os.path.join(script_directory, "assets", "fonts", "Roboto", "Roboto-Regular.ttf")) diff --git a/customtkinter/scaling_tracker.py b/customtkinter/scaling_tracker.py index 125bf75..2e9983a 100644 --- a/customtkinter/scaling_tracker.py +++ b/customtkinter/scaling_tracker.py @@ -124,7 +124,7 @@ class ScalingTracker: @classmethod def activate_high_dpi_awareness(cls): - """ make process DPI aware, customtkinter elemets will get scaled automatically, + """ make process DPI aware, customtkinter elements will get scaled automatically, only gets activated when CTk object is created """ if not cls.deactivate_automatic_dpi_awareness: @@ -135,28 +135,30 @@ class ScalingTracker: from ctypes import windll windll.shcore.SetProcessDpiAwareness(2) # Microsoft Docs: https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/ne-shellscalingapi-process_dpi_awareness - else: pass # DPI awareness on Linux not implemented @classmethod def get_window_dpi_scaling(cls, window) -> float: - if sys.platform == "darwin": - return 1 # scaling works automatically on macOS + if not cls.deactivate_automatic_dpi_awareness: + if sys.platform == "darwin": + return 1 # scaling works automatically on macOS - elif sys.platform.startswith("win"): - from ctypes import windll, pointer, wintypes + elif sys.platform.startswith("win"): + from ctypes import windll, pointer, wintypes - DPI100pc = 96 # DPI 96 is 100% scaling - DPI_type = 0 # MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2 - window_hwnd = wintypes.HWND(window.winfo_id()) - monitor_handle = windll.user32.MonitorFromWindow(window_hwnd, wintypes.DWORD(2)) # MONITOR_DEFAULTTONEAREST = 2 - x_dpi, y_dpi = wintypes.UINT(), wintypes.UINT() - windll.shcore.GetDpiForMonitor(monitor_handle, DPI_type, pointer(x_dpi), pointer(y_dpi)) - return (x_dpi.value + y_dpi.value) / (2 * DPI100pc) + DPI100pc = 96 # DPI 96 is 100% scaling + DPI_type = 0 # MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2 + window_hwnd = wintypes.HWND(window.winfo_id()) + monitor_handle = windll.user32.MonitorFromWindow(window_hwnd, wintypes.DWORD(2)) # MONITOR_DEFAULTTONEAREST = 2 + x_dpi, y_dpi = wintypes.UINT(), wintypes.UINT() + windll.shcore.GetDpiForMonitor(monitor_handle, DPI_type, pointer(x_dpi), pointer(y_dpi)) + return (x_dpi.value + y_dpi.value) / (2 * DPI100pc) + else: + return 1 # DPI awareness on Linux not implemented else: - return 1 # DPI awareness on Linux not implemented + return 1 @classmethod def check_dpi_scaling(cls): diff --git a/customtkinter/widgets/ctk_optionmenu.py b/customtkinter/widgets/ctk_optionmenu.py index ff36b64..a05291e 100644 --- a/customtkinter/widgets/ctk_optionmenu.py +++ b/customtkinter/widgets/ctk_optionmenu.py @@ -93,7 +93,7 @@ class CTkOptionMenu(CTkBaseClass): height=self.apply_widget_scaling(self.desired_height)) self.draw() - def set_dimensions(self, width=None, height=None): + def set_dimensions(self, width: int = None, height: int = None): super().set_dimensions(width, height) self.canvas.configure(width=self.apply_widget_scaling(self.desired_width), @@ -148,10 +148,9 @@ class CTkOptionMenu(CTkBaseClass): y_position=self.winfo_rooty() + self.current_height + 4, width=self.current_width, values=self.values, - command=self.set_value) + command=self.set) - def set_value(self, value): - print("set value", value) + def set(self, value: str): self.current_value = value if self.text_label is not None: @@ -159,6 +158,9 @@ class CTkOptionMenu(CTkBaseClass): else: self.draw() + def get(self) -> str: + return self.current_value + def configure(self, *args, **kwargs): require_redraw = False # some attribute changes require a call of self.draw() at the end @@ -181,10 +183,15 @@ class CTkOptionMenu(CTkBaseClass): require_redraw = True del kwargs["bg_color"] - if "hover_color" in kwargs: - self.hover_color = kwargs["hover_color"] + if "button_color" in kwargs: + self.button_color = kwargs["button_color"] require_redraw = True - del kwargs["hover_color"] + del kwargs["button_color"] + + if "button_hover_color" in kwargs: + self.button_hover_color = kwargs["button_hover_color"] + require_redraw = True + del kwargs["button_hover_color"] if "text_color" in kwargs: self.text_color = kwargs["text_color"] @@ -252,10 +259,10 @@ class CTkOptionMenu(CTkBaseClass): if self.state is not tkinter.DISABLED: self.open_dropdown_menu() - if self.function is not None: - # click animation: change color with .on_leave() and back to normal after 100ms with click_animation() - self.on_leave() - self.click_animation_running = True - self.after(100, self.click_animation) + # click animation: change color with .on_leave() and back to normal after 100ms with click_animation() + self.on_leave() + self.click_animation_running = True + self.after(100, self.click_animation) + if self.function is not None: self.function() diff --git a/examples/simple_example.py b/examples/simple_example.py index af3f210..8e054c3 100644 --- a/examples/simple_example.py +++ b/examples/simple_example.py @@ -58,7 +58,4 @@ s_var = tkinter.StringVar(value="on") switch_1 = customtkinter.CTkSwitch(master=frame_1) switch_1.pack(pady=y_padding, padx=10) -optionmenu_1 = customtkinter.CTkOptionMenu(master=frame_1, values=["option 1", "option 2", "number 42"]) -optionmenu_1.pack(pady=y_padding, padx=10) - app.mainloop() diff --git a/setup.cfg b/setup.cfg index 463c7e2..631c2d5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,7 +2,7 @@ name = customtkinter version = 4.1.0 description = Create modern looking GUIs with Python -long_description = file: README.md +long_description = file: Readme.md long_description_content_type = text/markdown url = https://github.com/TomSchimansky/CustomTkinter author = Tom Schimansky diff --git a/test/manual_integration_tests/test_combobox.py b/test/manual_integration_tests/test_combobox.py index 760e5d1..7aead78 100644 --- a/test/manual_integration_tests/test_combobox.py +++ b/test/manual_integration_tests/test_combobox.py @@ -1,4 +1,5 @@ from tkinter import * +import customtkinter ws = Tk() ws.title('PythonGuides') @@ -13,7 +14,7 @@ countries = ['Bahamas','Canada', 'Cuba','United States'] # setting variable for Integers variable = StringVar() -variable.set(countries[3]) +variable.set("test") # creating widget dropdown = OptionMenu( @@ -24,7 +25,10 @@ dropdown = OptionMenu( ) # positioning widget -dropdown.pack(expand=True) +dropdown.pack(pady=10, padx=10) + +optionmenu_1 = customtkinter.CTkOptionMenu(master=ws, values=["option 1", "option 2", "number 42"]) +optionmenu_1.pack(pady=10, padx=10) # infinite loop ws.mainloop()