mirror of
https://github.com/TomSchimansky/CustomTkinter.git
synced 2023-08-10 21:13:13 +03:00
added scaling tracker
This commit is contained in:
parent
5ede252b2f
commit
17d4b9fcba
@ -16,7 +16,7 @@ from .widgets.customtkinter_toplevel import CTkToplevel
|
|||||||
|
|
||||||
from .customtkinter_settings import CTkSettings
|
from .customtkinter_settings import CTkSettings
|
||||||
from .appearance_mode_tracker import AppearanceModeTracker
|
from .appearance_mode_tracker import AppearanceModeTracker
|
||||||
from .customtkinter_theme_manager import CTkThemeManager
|
from .theme_manager import CTkThemeManager
|
||||||
|
|
||||||
from distutils.version import StrictVersion as Version
|
from distutils.version import StrictVersion as Version
|
||||||
import tkinter
|
import tkinter
|
||||||
|
@ -3,11 +3,9 @@ import sys
|
|||||||
|
|
||||||
class CTkSettings:
|
class CTkSettings:
|
||||||
|
|
||||||
scaling_factor = 1
|
|
||||||
circle_font_is_ready = False
|
circle_font_is_ready = False
|
||||||
hand_cursor_enabled = True
|
hand_cursor_enabled = True
|
||||||
preferred_drawing_method = None
|
preferred_drawing_method = None
|
||||||
|
|
||||||
radius_to_char_fine = None
|
radius_to_char_fine = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -42,7 +40,6 @@ class CTkSettings:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def print_settings(cls):
|
def print_settings(cls):
|
||||||
print(f"CTkSettings current values:")
|
print(f"CTkSettings current values:")
|
||||||
print(f"scaling_factor = {cls.scaling_factor}")
|
|
||||||
print(f"circle_font_is_ready = {cls.circle_font_is_ready}")
|
print(f"circle_font_is_ready = {cls.circle_font_is_ready}")
|
||||||
print(f"hand_cursor_enabled = {cls.hand_cursor_enabled}")
|
print(f"hand_cursor_enabled = {cls.hand_cursor_enabled}")
|
||||||
print(f"preferred_drawing_method = {cls.preferred_drawing_method}")
|
print(f"preferred_drawing_method = {cls.preferred_drawing_method}")
|
||||||
|
100
customtkinter/scaling_tracker.py
Normal file
100
customtkinter/scaling_tracker.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import tkinter
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
class ScalingTracker:
|
||||||
|
|
||||||
|
window_widgets_dict = {} # contains window objects as keys with list of widget callbacks as elements
|
||||||
|
|
||||||
|
window_dpi_scaling_dict = {} # contains window objects as keys and corresponding DPI values
|
||||||
|
user_scaling = 1 # scale change of all widgets and windows
|
||||||
|
|
||||||
|
update_loop_running = False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_widget_scaling(cls, widget):
|
||||||
|
window_root = cls.get_window_root_of_widget(widget)
|
||||||
|
return cls.window_dpi_scaling_dict[window_root] * cls.user_scaling
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_window_scaling(cls, window):
|
||||||
|
return cls.window_dpi_scaling_dict[window] * cls.user_scaling
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_user_scaling(cls, user_scaling_factor):
|
||||||
|
cls.user_scaling = user_scaling_factor
|
||||||
|
cls.update_scaling_callbacks()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_window_root_of_widget(cls, widget):
|
||||||
|
current_widget = widget
|
||||||
|
|
||||||
|
while isinstance(current_widget, tkinter.Tk) is False and\
|
||||||
|
isinstance(current_widget, tkinter.Toplevel) is False:
|
||||||
|
current_widget = current_widget.master
|
||||||
|
|
||||||
|
return current_widget
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def update_scaling_callbacks(cls):
|
||||||
|
for window, callback_list in cls.window_widgets_dict.items():
|
||||||
|
for callback in callback_list:
|
||||||
|
callback(cls.window_dpi_scaling_dict[window])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def add_widget(cls, widget_callback, widget):
|
||||||
|
window_root = cls.get_window_root_of_widget(widget)
|
||||||
|
|
||||||
|
if window_root not in cls.window_widgets_dict:
|
||||||
|
cls.window_widgets_dict[window_root] = [widget_callback]
|
||||||
|
else:
|
||||||
|
cls.window_widgets_dict[window_root].append(widget_callback)
|
||||||
|
|
||||||
|
if window_root not in cls.window_dpi_scaling_dict:
|
||||||
|
cls.window_dpi_scaling_dict[window_root] = cls.get_window_dpi_value(window_root)
|
||||||
|
|
||||||
|
if not cls.update_loop_running:
|
||||||
|
window_root.after(100, cls.check_dpi_scaling)
|
||||||
|
cls.update_loop_running = True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def add_window(cls, window_callback, window):
|
||||||
|
if window not in cls.window_widgets_dict:
|
||||||
|
cls.window_widgets_dict[window] = [window_callback]
|
||||||
|
else:
|
||||||
|
cls.window_widgets_dict[window].append(window_callback)
|
||||||
|
|
||||||
|
if window not in cls.window_dpi_scaling_dict:
|
||||||
|
cls.window_dpi_scaling_dict[window] = cls.get_window_dpi_value(window)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_window_dpi_value(cls, window):
|
||||||
|
if sys.platform == "darwin":
|
||||||
|
return 1 # scaling works automatically on macOS
|
||||||
|
|
||||||
|
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)
|
||||||
|
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
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def check_dpi_scaling(cls):
|
||||||
|
# find an existing tkinter object for the next call of .after()
|
||||||
|
for root_tk in cls.window_widgets_dict.keys():
|
||||||
|
try:
|
||||||
|
root_tk.after(500, cls.check_dpi_scaling)
|
||||||
|
return
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
|
||||||
|
cls.update_loop_running = False
|
||||||
|
|
@ -6,9 +6,10 @@ from .customtkinter_tk import CTk
|
|||||||
from .customtkinter_frame import CTkFrame
|
from .customtkinter_frame import CTkFrame
|
||||||
from .customtkinter_canvas import CTkCanvas
|
from .customtkinter_canvas import CTkCanvas
|
||||||
from customtkinter.appearance_mode_tracker import AppearanceModeTracker
|
from customtkinter.appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..customtkinter_theme_manager import CTkThemeManager
|
from ..theme_manager import CTkThemeManager
|
||||||
from ..customtkinter_settings import CTkSettings
|
from ..customtkinter_settings import CTkSettings
|
||||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||||
|
from ..scaling_tracker import ScalingTracker
|
||||||
|
|
||||||
|
|
||||||
class CTkButton(tkinter.Frame):
|
class CTkButton(tkinter.Frame):
|
||||||
@ -61,6 +62,9 @@ class CTkButton(tkinter.Frame):
|
|||||||
AppearanceModeTracker.add(self.set_appearance_mode, self)
|
AppearanceModeTracker.add(self.set_appearance_mode, self)
|
||||||
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
|
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
|
||||||
|
|
||||||
|
ScalingTracker.add_widget(self.set_scaling, self)
|
||||||
|
self.scaling = ScalingTracker.get_widget_scaling(self)
|
||||||
|
|
||||||
self.configure_basic_grid()
|
self.configure_basic_grid()
|
||||||
|
|
||||||
# color variables
|
# color variables
|
||||||
@ -72,7 +76,7 @@ class CTkButton(tkinter.Frame):
|
|||||||
# shape and size
|
# shape and size
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
self.configure(width=self.width, height=self.height)
|
self.configure(width=self.width * self.scaling, height=self.height * self.scaling)
|
||||||
self.corner_radius = CTkThemeManager.theme["shape"]["button_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
self.corner_radius = CTkThemeManager.theme["shape"]["button_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||||
self.border_width = CTkThemeManager.theme["shape"]["button_border_width"] if border_width == "default_theme" else border_width
|
self.border_width = CTkThemeManager.theme["shape"]["button_border_width"] if border_width == "default_theme" else border_width
|
||||||
|
|
||||||
@ -95,8 +99,8 @@ class CTkButton(tkinter.Frame):
|
|||||||
|
|
||||||
self.canvas = CTkCanvas(master=self,
|
self.canvas = CTkCanvas(master=self,
|
||||||
highlightthickness=0,
|
highlightthickness=0,
|
||||||
width=self.width,
|
width=self.width * self.scaling,
|
||||||
height=self.height)
|
height=self.height * self.scaling)
|
||||||
self.canvas.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="nsew")
|
self.canvas.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="nsew")
|
||||||
|
|
||||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||||
@ -414,3 +418,9 @@ class CTkButton(tkinter.Frame):
|
|||||||
self.bg_color = self.master.cget("bg")
|
self.bg_color = self.master.cget("bg")
|
||||||
|
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
|
def set_scaling(self, scaling_factor):
|
||||||
|
self.scaling = scaling_factor
|
||||||
|
self.configure(width=self.width * self.scaling, height=self.height * self.scaling)
|
||||||
|
self.canvas.configure(width=self.width * self.scaling, height=self.height * self.scaling)
|
||||||
|
self.draw(no_color_updates=True)
|
||||||
|
@ -6,7 +6,7 @@ from .customtkinter_tk import CTk
|
|||||||
from .customtkinter_frame import CTkFrame
|
from .customtkinter_frame import CTkFrame
|
||||||
from .customtkinter_canvas import CTkCanvas
|
from .customtkinter_canvas import CTkCanvas
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..customtkinter_theme_manager import CTkThemeManager
|
from ..theme_manager import CTkThemeManager
|
||||||
from ..customtkinter_settings import CTkSettings
|
from ..customtkinter_settings import CTkSettings
|
||||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ from .customtkinter_tk import CTk
|
|||||||
from .customtkinter_frame import CTkFrame
|
from .customtkinter_frame import CTkFrame
|
||||||
from .customtkinter_canvas import CTkCanvas
|
from .customtkinter_canvas import CTkCanvas
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..customtkinter_theme_manager import CTkThemeManager
|
from ..theme_manager import CTkThemeManager
|
||||||
from ..customtkinter_settings import CTkSettings
|
from ..customtkinter_settings import CTkSettings
|
||||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import tkinter.ttk as ttk
|
|||||||
from .customtkinter_tk import CTk
|
from .customtkinter_tk import CTk
|
||||||
from .customtkinter_canvas import CTkCanvas
|
from .customtkinter_canvas import CTkCanvas
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..customtkinter_theme_manager import CTkThemeManager
|
from ..theme_manager import CTkThemeManager
|
||||||
from ..customtkinter_settings import CTkSettings
|
from ..customtkinter_settings import CTkSettings
|
||||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ from .customtkinter_frame import CTkFrame
|
|||||||
from .customtkinter_toplevel import CTkToplevel
|
from .customtkinter_toplevel import CTkToplevel
|
||||||
from .customtkinter_button import CTkButton
|
from .customtkinter_button import CTkButton
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..customtkinter_theme_manager import CTkThemeManager
|
from ..theme_manager import CTkThemeManager
|
||||||
|
|
||||||
|
|
||||||
class CTkInputDialog:
|
class CTkInputDialog:
|
||||||
|
@ -5,7 +5,7 @@ from .customtkinter_tk import CTk
|
|||||||
from .customtkinter_frame import CTkFrame
|
from .customtkinter_frame import CTkFrame
|
||||||
from .customtkinter_canvas import CTkCanvas
|
from .customtkinter_canvas import CTkCanvas
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..customtkinter_theme_manager import CTkThemeManager
|
from ..theme_manager import CTkThemeManager
|
||||||
from ..customtkinter_settings import CTkSettings
|
from ..customtkinter_settings import CTkSettings
|
||||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ from .customtkinter_tk import CTk
|
|||||||
from .customtkinter_frame import CTkFrame
|
from .customtkinter_frame import CTkFrame
|
||||||
from .customtkinter_canvas import CTkCanvas
|
from .customtkinter_canvas import CTkCanvas
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..customtkinter_theme_manager import CTkThemeManager
|
from ..theme_manager import CTkThemeManager
|
||||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||||
from ..customtkinter_settings import CTkSettings
|
from ..customtkinter_settings import CTkSettings
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ from .customtkinter_tk import CTk
|
|||||||
from .customtkinter_frame import CTkFrame
|
from .customtkinter_frame import CTkFrame
|
||||||
from .customtkinter_canvas import CTkCanvas
|
from .customtkinter_canvas import CTkCanvas
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..customtkinter_theme_manager import CTkThemeManager
|
from ..theme_manager import CTkThemeManager
|
||||||
from ..customtkinter_settings import CTkSettings
|
from ..customtkinter_settings import CTkSettings
|
||||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ from .customtkinter_tk import CTk
|
|||||||
from .customtkinter_frame import CTkFrame
|
from .customtkinter_frame import CTkFrame
|
||||||
from .customtkinter_canvas import CTkCanvas
|
from .customtkinter_canvas import CTkCanvas
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..customtkinter_theme_manager import CTkThemeManager
|
from ..theme_manager import CTkThemeManager
|
||||||
from ..customtkinter_settings import CTkSettings
|
from ..customtkinter_settings import CTkSettings
|
||||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ from .customtkinter_tk import CTk
|
|||||||
from .customtkinter_frame import CTkFrame
|
from .customtkinter_frame import CTkFrame
|
||||||
from .customtkinter_canvas import CTkCanvas
|
from .customtkinter_canvas import CTkCanvas
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..customtkinter_theme_manager import CTkThemeManager
|
from ..theme_manager import CTkThemeManager
|
||||||
from ..customtkinter_settings import CTkSettings
|
from ..customtkinter_settings import CTkSettings
|
||||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import platform
|
|||||||
import ctypes
|
import ctypes
|
||||||
|
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..customtkinter_theme_manager import CTkThemeManager
|
from ..theme_manager import CTkThemeManager
|
||||||
|
|
||||||
|
|
||||||
class CTk(tkinter.Tk):
|
class CTk(tkinter.Tk):
|
||||||
|
@ -6,7 +6,7 @@ import platform
|
|||||||
import ctypes
|
import ctypes
|
||||||
|
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..customtkinter_theme_manager import CTkThemeManager
|
from ..theme_manager import CTkThemeManager
|
||||||
|
|
||||||
|
|
||||||
class CTkToplevel(tkinter.Toplevel):
|
class CTkToplevel(tkinter.Toplevel):
|
||||||
|
@ -15,6 +15,8 @@ class ExampleApp(customtkinter.CTk):
|
|||||||
window = customtkinter.CTkToplevel(self)
|
window = customtkinter.CTkToplevel(self)
|
||||||
window.geometry("400x200")
|
window.geometry("400x200")
|
||||||
|
|
||||||
|
print(window.master.winfo_class())
|
||||||
|
|
||||||
label = customtkinter.CTkLabel(window, text="CTkToplevel window")
|
label = customtkinter.CTkLabel(window, text="CTkToplevel window")
|
||||||
label.pack(side="top", fill="both", expand=True, padx=40, pady=40)
|
label.pack(side="top", fill="both", expand=True, padx=40, pady=40)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user