diff --git a/customtkinter/__init__.py b/customtkinter/__init__.py index 58761ee..4cdeb9c 100644 --- a/customtkinter/__init__.py +++ b/customtkinter/__init__.py @@ -14,9 +14,10 @@ from .widgets.ctk_canvas import CTkCanvas from .widgets.ctk_switch import CTkSwitch from .widgets.ctk_toplevel import CTkToplevel -from .customtkinter_settings import CTkSettings +from .ctk_settings import CTkSettings from .appearance_mode_tracker import AppearanceModeTracker from .theme_manager import CTkThemeManager +from .scaling_tracker import ScalingTracker from distutils.version import StrictVersion as Version import tkinter diff --git a/customtkinter/customtkinter_draw_engine.py b/customtkinter/ctk_draw_engine.py similarity index 100% rename from customtkinter/customtkinter_draw_engine.py rename to customtkinter/ctk_draw_engine.py diff --git a/customtkinter/customtkinter_settings.py b/customtkinter/ctk_settings.py similarity index 100% rename from customtkinter/customtkinter_settings.py rename to customtkinter/ctk_settings.py diff --git a/customtkinter/widgets/ctk_button.py b/customtkinter/widgets/ctk_button.py index 46a620a..2ce783f 100644 --- a/customtkinter/widgets/ctk_button.py +++ b/customtkinter/widgets/ctk_button.py @@ -2,9 +2,9 @@ import tkinter import sys from .ctk_canvas import CTkCanvas -from ..customtkinter_theme_manager import CTkThemeManager -from ..customtkinter_settings import CTkSettings -from ..customtkinter_draw_engine import CTkDrawEngine +from ..theme_manager import CTkThemeManager +from ..ctk_settings import CTkSettings +from ..ctk_draw_engine import CTkDrawEngine from .widget_base_class import CTkBaseClass @@ -65,8 +65,8 @@ class CTkButton(CTkBaseClass): self.canvas = CTkCanvas(master=self, highlightthickness=0, - width=self.width, - height=self.height) + width=self.width * self.scaling, + height=self.height * self.scaling) self.canvas.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="nsew") self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method) @@ -75,9 +75,7 @@ class CTkButton(CTkBaseClass): self.canvas.bind("", self.on_leave) self.canvas.bind("", self.clicked) self.canvas.bind("", self.clicked) - - # Each time an item is resized due to pack position mode, the binding Configure is called on the widget - self.bind('', self.update_dimensions) + self.bind('', self.update_dimensions_event) self.set_cursor() self.draw() # initial draw @@ -90,7 +88,10 @@ class CTkButton(CTkBaseClass): self.grid_columnconfigure(1, weight=1) def draw(self, no_color_updates=False): - requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, self.border_width) + requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width * self.scaling, + self.height * self.scaling, + self.corner_radius * self.scaling, + self.border_width * self.scaling) if no_color_updates is False or requires_recoloring: @@ -115,7 +116,9 @@ class CTkButton(CTkBaseClass): if self.text is not None and self.text != "": if self.text_label is None: - self.text_label = tkinter.Label(master=self, font=self.text_font, textvariable=self.textvariable) + self.text_label = tkinter.Label(master=self, + font=self.apply_font_scaling(self.text_font), + textvariable=self.textvariable) self.text_label.bind("", self.on_enter) self.text_label.bind("", self.on_leave) @@ -172,26 +175,35 @@ class CTkButton(CTkBaseClass): # create grid layout with just an image given if self.image_label is not None and self.text_label is None: - self.image_label.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="", pady=self.border_width) + self.image_label.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="", pady=self.border_width * self.scaling) # create grid layout with just text given if self.image_label is None and self.text_label is not None: - self.text_label.grid(row=0, column=0, padx=self.corner_radius, pady=self.border_width, rowspan=2, columnspan=2, sticky="") + self.text_label.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="", + padx=self.corner_radius * self.scaling, pady=self.border_width * self.scaling) # create grid layout of image and text label in 2x2 grid system with given compound if self.image_label is not None and self.text_label is not None: if self.compound == tkinter.LEFT or self.compound == "left": - self.image_label.grid(row=0, column=0, padx=(max(self.corner_radius, self.border_width), 2), sticky="e", rowspan=2, columnspan=1, pady=self.border_width) - self.text_label.grid(row=0, column=1, padx=(2, max(self.corner_radius, self.border_width)), sticky="w", rowspan=2, columnspan=1, pady=self.border_width) + self.image_label.grid(row=0, column=0, sticky="e", rowspan=2, columnspan=1, + padx=(max(self.corner_radius * self.scaling, self.border_width * self.scaling), 2), pady=self.border_width * self.scaling) + self.text_label.grid(row=0, column=1, sticky="w", rowspan=2, columnspan=1, + padx=(2, max(self.corner_radius * self.scaling, self.border_width * self.scaling)), pady=self.border_width * self.scaling) elif self.compound == tkinter.TOP or self.compound == "top": - self.image_label.grid(row=0, column=0, padx=max(self.corner_radius, self.border_width), sticky="s", columnspan=2, rowspan=1, pady=(self.border_width, 2)) - self.text_label.grid(row=1, column=0, padx=max(self.corner_radius, self.border_width), sticky="n", columnspan=2, rowspan=1, pady=(2, self.border_width)) + self.image_label.grid(row=0, column=0, sticky="s", columnspan=2, rowspan=1, + padx=max(self.corner_radius * self.scaling, self.border_width * self.scaling), pady=(self.border_width * self.scaling, 2)) + self.text_label.grid(row=1, column=0, sticky="n", columnspan=2, rowspan=1, + padx=max(self.corner_radius * self.scaling, self.border_width * self.scaling), pady=(2, self.border_width * self.scaling)) elif self.compound == tkinter.RIGHT or self.compound == "right": - self.image_label.grid(row=0, column=1, padx=(2, max(self.corner_radius, self.border_width)), sticky="w", rowspan=2, columnspan=1, pady=self.border_width) - self.text_label.grid(row=0, column=0, padx=(max(self.corner_radius, self.border_width), 2), sticky="e", rowspan=2, columnspan=1, pady=self.border_width) + self.image_label.grid(row=0, column=1, sticky="w", rowspan=2, columnspan=1, + padx=(2, max(self.corner_radius * self.scaling, self.border_width * self.scaling)), pady=self.border_width * self.scaling) + self.text_label.grid(row=0, column=0, sticky="e", rowspan=2, columnspan=1, + padx=(max(self.corner_radius * self.scaling, self.border_width * self.scaling), 2), pady=self.border_width * self.scaling) elif self.compound == tkinter.BOTTOM or self.compound == "bottom": - self.image_label.grid(row=1, column=0, padx=max(self.corner_radius, self.border_width), sticky="n", columnspan=2, rowspan=1, pady=(2, self.border_width)) - self.text_label.grid(row=0, column=0, padx=max(self.corner_radius, self.border_width), sticky="s", columnspan=2, rowspan=1, pady=(self.border_width, 2)) + self.image_label.grid(row=1, column=0, sticky="n", columnspan=2, rowspan=1, + padx=max(self.corner_radius * self.scaling, self.border_width * self.scaling), pady=(2, self.border_width * self.scaling)) + self.text_label.grid(row=0, column=0, sticky="s", columnspan=2, rowspan=1, + padx=max(self.corner_radius * self.scaling, self.border_width * self.scaling), pady=(self.border_width * self.scaling, 2)) def configure(self, *args, **kwargs): require_redraw = False # some attribute changes require a call of self.draw() at the end diff --git a/customtkinter/widgets/ctk_canvas.py b/customtkinter/widgets/ctk_canvas.py index 0f0fc66..074f5fe 100644 --- a/customtkinter/widgets/ctk_canvas.py +++ b/customtkinter/widgets/ctk_canvas.py @@ -1,5 +1,5 @@ import tkinter -from ..customtkinter_settings import CTkSettings +from ..ctk_settings import CTkSettings class CTkCanvas(tkinter.Canvas): diff --git a/customtkinter/widgets/ctk_checkbox.py b/customtkinter/widgets/ctk_checkbox.py index 9d78b64..95df643 100644 --- a/customtkinter/widgets/ctk_checkbox.py +++ b/customtkinter/widgets/ctk_checkbox.py @@ -2,9 +2,9 @@ import tkinter import sys from .ctk_canvas import CTkCanvas -from ..customtkinter_theme_manager import CTkThemeManager -from ..customtkinter_settings import CTkSettings -from ..customtkinter_draw_engine import CTkDrawEngine +from ..theme_manager import CTkThemeManager +from ..ctk_settings import CTkSettings +from ..ctk_draw_engine import CTkDrawEngine from .widget_base_class import CTkBaseClass @@ -68,14 +68,15 @@ class CTkCheckBox(CTkBaseClass): # configure grid system (1x3) self.grid_columnconfigure(0, weight=0) - self.grid_columnconfigure(1, weight=0, minsize=6) + self.grid_columnconfigure(1, weight=0, minsize=6 * self.scaling) self.grid_columnconfigure(2, weight=1) + self.grid_rowconfigure(0, weight=1) self.canvas = CTkCanvas(master=self, highlightthickness=0, - width=self.width, - height=self.height) - self.canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=1) + width=self.width * self.scaling, + height=self.height * self.scaling) + self.canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=1, rowspan=1) self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method) if self.hover is True: @@ -103,15 +104,20 @@ class CTkCheckBox(CTkBaseClass): super().destroy() def draw(self, no_color_updates=False): - requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, self.border_width) + requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width * self.scaling, + self.height * self.scaling, + self.corner_radius * self.scaling, + self.border_width * self.scaling) if self.check_state is True: - self.draw_engine.draw_checkmark(self.width, self.height, self.height * 0.58) + self.draw_engine.draw_checkmark(self.width * self.scaling, + self.height * self.scaling, + self.height * 0.58 * self.scaling) else: self.canvas.delete("checkmark") - self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode)) self.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode)) + self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode)) if self.check_state is True: self.canvas.itemconfig("inner_parts", @@ -134,11 +140,12 @@ class CTkCheckBox(CTkBaseClass): fill=CTkThemeManager.single_color(self.border_color, self.appearance_mode)) if self.text_label is None: + print("create label") self.text_label = tkinter.Label(master=self, bd=0, text=self.text, justify=tkinter.LEFT, - font=self.text_font) + font=self.apply_font_scaling(self.text_font)) self.text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w") self.text_label["anchor"] = "w" diff --git a/customtkinter/widgets/ctk_entry.py b/customtkinter/widgets/ctk_entry.py index a473b83..a17ea5c 100644 --- a/customtkinter/widgets/ctk_entry.py +++ b/customtkinter/widgets/ctk_entry.py @@ -1,9 +1,9 @@ import tkinter from .ctk_canvas import CTkCanvas -from ..customtkinter_theme_manager import CTkThemeManager -from ..customtkinter_settings import CTkSettings -from ..customtkinter_draw_engine import CTkDrawEngine +from ..theme_manager import CTkThemeManager +from ..ctk_settings import CTkSettings +from ..ctk_draw_engine import CTkDrawEngine from .widget_base_class import CTkBaseClass @@ -46,8 +46,8 @@ class CTkEntry(CTkBaseClass): self.canvas = CTkCanvas(master=self, highlightthickness=0, - width=self.width, - height=self.height) + width=self.width * self.scaling, + height=self.height * self.scaling) self.canvas.grid(column=0, row=0, sticky="we") self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method) @@ -55,11 +55,12 @@ class CTkEntry(CTkBaseClass): bd=0, width=1, highlightthickness=0, - font=self.text_font, + font=self.apply_font_scaling(self.text_font), **kwargs) - self.entry.grid(column=0, row=0, sticky="we", padx=self.corner_radius if self.corner_radius >= 6 else 6) + self.entry.grid(column=0, row=0, sticky="we", + padx=self.corner_radius * self.scaling if self.corner_radius >= 6 * self.scaling else 6 * self.scaling) - super().bind('', self.update_dimensions) + super().bind('', self.update_dimensions_event) self.entry.bind('', self.set_placeholder) self.entry.bind('', self.clear_placeholder) @@ -90,7 +91,10 @@ class CTkEntry(CTkBaseClass): def draw(self, no_color_updates=False): self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode)) - requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, self.border_width) + requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width * self.scaling, + self.height * self.scaling, + self.corner_radius * self.scaling, + self.border_width * self.scaling) if CTkThemeManager.single_color(self.fg_color, self.appearance_mode) is not None: self.canvas.itemconfig("inner_parts", diff --git a/customtkinter/widgets/ctk_frame.py b/customtkinter/widgets/ctk_frame.py index 529f0cf..dcb27f6 100644 --- a/customtkinter/widgets/ctk_frame.py +++ b/customtkinter/widgets/ctk_frame.py @@ -1,9 +1,9 @@ import tkinter from .ctk_canvas import CTkCanvas -from ..customtkinter_theme_manager import CTkThemeManager -from ..customtkinter_settings import CTkSettings -from ..customtkinter_draw_engine import CTkDrawEngine +from ..theme_manager import CTkThemeManager +from ..ctk_settings import CTkSettings +from ..ctk_draw_engine import CTkDrawEngine from .widget_base_class import CTkBaseClass @@ -41,13 +41,13 @@ class CTkFrame(CTkBaseClass): self.canvas = CTkCanvas(master=self, highlightthickness=0, - width=self.width, - height=self.height) + width=self.width * self.scaling, + height=self.height * self.scaling) self.canvas.place(x=0, y=0, relwidth=1, relheight=1) self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode)) self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method) - self.bind('', self.update_dimensions) + self.bind('', self.update_dimensions_event) self.draw() @@ -64,7 +64,10 @@ class CTkFrame(CTkBaseClass): def draw(self, no_color_updates=False): - requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, self.border_width) + requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width * self.scaling, + self.height * self.scaling, + self.corner_radius * self.scaling, + self.border_width * self.scaling) if no_color_updates is False or requires_recoloring: self.canvas.itemconfig("inner_parts", diff --git a/customtkinter/widgets/ctk_label.py b/customtkinter/widgets/ctk_label.py index 4ed6925..e63a2ad 100644 --- a/customtkinter/widgets/ctk_label.py +++ b/customtkinter/widgets/ctk_label.py @@ -1,9 +1,9 @@ import tkinter from .ctk_canvas import CTkCanvas -from ..customtkinter_theme_manager import CTkThemeManager -from ..customtkinter_settings import CTkSettings -from ..customtkinter_draw_engine import CTkDrawEngine +from ..theme_manager import CTkThemeManager +from ..ctk_settings import CTkSettings +from ..ctk_draw_engine import CTkDrawEngine from .widget_base_class import CTkBaseClass @@ -45,8 +45,8 @@ class CTkLabel(CTkBaseClass): self.canvas = CTkCanvas(master=self, highlightthickness=0, - width=self.width, - height=self.height) + width=self.width * self.scaling, + height=self.height * self.scaling) self.canvas.grid(row=0, column=0, sticky="nswe") self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method) @@ -54,15 +54,18 @@ class CTkLabel(CTkBaseClass): highlightthickness=0, bd=0, text=self.text, - font=self.text_font, + font=self.apply_font_scaling(self.text_font), **kwargs) self.text_label.grid(row=0, column=0, padx=self.corner_radius) - self.bind('', self.update_dimensions) + self.bind('', self.update_dimensions_event) self.draw() def draw(self, no_color_updates=False): - requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, 0) + requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width * self.scaling, + self.height * self.scaling, + self.corner_radius * self.scaling, + 0) self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode)) diff --git a/customtkinter/widgets/ctk_progressbar.py b/customtkinter/widgets/ctk_progressbar.py index aa536c0..62b0125 100644 --- a/customtkinter/widgets/ctk_progressbar.py +++ b/customtkinter/widgets/ctk_progressbar.py @@ -1,9 +1,9 @@ import tkinter from .ctk_canvas import CTkCanvas -from ..customtkinter_theme_manager import CTkThemeManager -from ..customtkinter_draw_engine import CTkDrawEngine -from ..customtkinter_settings import CTkSettings +from ..theme_manager import CTkThemeManager +from ..ctk_draw_engine import CTkDrawEngine +from ..ctk_settings import CTkSettings from .widget_base_class import CTkBaseClass @@ -40,15 +40,18 @@ class CTkProgressBar(CTkBaseClass): self.border_width = CTkThemeManager.theme["shape"]["progressbar_border_width"] if border_width == "default_theme" else border_width self.value = 0.5 + self.grid_rowconfigure(1, weight=1) + self.grid_columnconfigure(1, weight=1) + self.canvas = CTkCanvas(master=self, highlightthickness=0, - width=self.width, - height=self.height) - self.canvas.place(x=0, y=0, relwidth=1, relheight=1) + width=self.width * self.scaling, + height=self.height * self.scaling) + self.canvas.grid(row=0, column=0, rowspan=1, columnspan=1) self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method) # Each time an item is resized due to pack position mode, the binding Configure is called on the widget - self.bind('', self.update_dimensions) + self.bind('', self.update_dimensions_event) self.draw() # initial draw @@ -65,8 +68,13 @@ class CTkProgressBar(CTkBaseClass): super().destroy() def draw(self, no_color_updates=False): + print("progress", self.scaling) - requires_recoloring = self.draw_engine.draw_rounded_progress_bar_with_border(self.width, self.height, self.corner_radius, self.border_width, self.value, "w") + requires_recoloring = self.draw_engine.draw_rounded_progress_bar_with_border(self.width * self.scaling, + self.height * self.scaling, + self.corner_radius * self.scaling, + self.border_width * self.scaling, + self.value, "w") if no_color_updates is False or requires_recoloring: self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode)) diff --git a/customtkinter/widgets/ctk_radiobutton.py b/customtkinter/widgets/ctk_radiobutton.py index 1b5ef94..941fd53 100644 --- a/customtkinter/widgets/ctk_radiobutton.py +++ b/customtkinter/widgets/ctk_radiobutton.py @@ -2,9 +2,9 @@ import tkinter import sys from .ctk_canvas import CTkCanvas -from ..customtkinter_theme_manager import CTkThemeManager -from ..customtkinter_settings import CTkSettings -from ..customtkinter_draw_engine import CTkDrawEngine +from ..theme_manager import CTkThemeManager +from ..ctk_settings import CTkSettings +from ..ctk_draw_engine import CTkDrawEngine from .widget_base_class import CTkBaseClass @@ -65,13 +65,13 @@ class CTkRadioButton(CTkBaseClass): # configure grid system (3x1) self.grid_columnconfigure(0, weight=0) - self.grid_columnconfigure(1, weight=0, minsize=6) + self.grid_columnconfigure(1, weight=0, minsize=6 * self.scaling) self.grid_columnconfigure(2, weight=1) self.canvas = CTkCanvas(master=self, highlightthickness=0, - width=self.width, - height=self.height) + width=self.width * self.scaling, + height=self.height * self.scaling) self.canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=1) self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method) @@ -97,7 +97,10 @@ class CTkRadioButton(CTkBaseClass): super().destroy() def draw(self, no_color_updates=False): - requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, self.border_width) + requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width * self.scaling, + self.height * self.scaling, + self.corner_radius * self.scaling, + self.border_width * self.scaling) self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode)) self.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode)) @@ -120,7 +123,7 @@ class CTkRadioButton(CTkBaseClass): bd=0, text=self.text, justify=tkinter.LEFT, - font=self.text_font) + font=self.apply_font_scaling(self.text_font)) self.text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w") self.text_label["anchor"] = "w" diff --git a/customtkinter/widgets/ctk_slider.py b/customtkinter/widgets/ctk_slider.py index 7ef2c11..fcb9538 100644 --- a/customtkinter/widgets/ctk_slider.py +++ b/customtkinter/widgets/ctk_slider.py @@ -2,9 +2,9 @@ import tkinter import sys from .ctk_canvas import CTkCanvas -from ..customtkinter_theme_manager import CTkThemeManager -from ..customtkinter_settings import CTkSettings -from ..customtkinter_draw_engine import CTkDrawEngine +from ..theme_manager import CTkThemeManager +from ..ctk_settings import CTkSettings +from ..ctk_draw_engine import CTkDrawEngine from .widget_base_class import CTkBaseClass @@ -64,8 +64,8 @@ class CTkSlider(CTkBaseClass): self.canvas = CTkCanvas(master=self, highlightthickness=0, - width=self.width, - height=self.height) + width=self.width * self.scaling, + height=self.height * self.scaling) self.canvas.grid(column=0, row=0, sticky="nswe") self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method) @@ -75,7 +75,7 @@ class CTkSlider(CTkBaseClass): self.canvas.bind("", self.clicked) # Each time an item is resized due to pack position mode, the binding Configure is called on the widget - self.bind('', self.update_dimensions) + self.bind('', self.update_dimensions_event) self.set_cursor() self.draw() # initial draw @@ -104,8 +104,13 @@ class CTkSlider(CTkBaseClass): self.configure(cursor="hand2") def draw(self, no_color_updates=False): - requires_recoloring = self.draw_engine.draw_rounded_slider_with_border_and_button(self.width, self.height, self.corner_radius, self.border_width, - self.button_length, self.button_corner_radius, self.value, "w") + requires_recoloring = self.draw_engine.draw_rounded_slider_with_border_and_button(self.width * self.scaling, + self.height * self.scaling, + self.corner_radius * self.scaling, + self.border_width * self.scaling, + self.button_length * self.scaling, + self.button_corner_radius * self.scaling, + self.value, "w") if no_color_updates is False or requires_recoloring: self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode)) @@ -131,7 +136,7 @@ class CTkSlider(CTkBaseClass): outline=CTkThemeManager.single_color(self.button_color, self.appearance_mode)) def clicked(self, event=None): - self.value = event.x / self.width + self.value = (event.x / self.width) / self.scaling if self.value > 1: self.value = 1 diff --git a/customtkinter/widgets/ctk_switch.py b/customtkinter/widgets/ctk_switch.py index 467596b..073d5e0 100644 --- a/customtkinter/widgets/ctk_switch.py +++ b/customtkinter/widgets/ctk_switch.py @@ -2,9 +2,9 @@ import tkinter import sys from .ctk_canvas import CTkCanvas -from ..customtkinter_theme_manager import CTkThemeManager -from ..customtkinter_settings import CTkSettings -from ..customtkinter_draw_engine import CTkDrawEngine +from ..theme_manager import CTkThemeManager +from ..ctk_settings import CTkSettings +from ..ctk_draw_engine import CTkDrawEngine from .widget_base_class import CTkBaseClass @@ -70,13 +70,13 @@ class CTkSwitch(CTkBaseClass): # configure grid system (3x1) self.grid_columnconfigure(0, weight=1) - self.grid_columnconfigure(1, weight=0, minsize=6) + self.grid_columnconfigure(1, weight=0, minsize=6 * self.scaling) self.grid_columnconfigure(2, weight=0) self.canvas = CTkCanvas(master=self, highlightthickness=0, - width=self.width, - height=self.height) + width=self.width * self.scaling, + height=self.height * self.scaling) self.canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=1, sticky="nswe") self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method) @@ -110,11 +110,21 @@ class CTkSwitch(CTkBaseClass): def draw(self, no_color_updates=False): if self.check_state is True: - requires_recoloring = self.draw_engine.draw_rounded_slider_with_border_and_button(self.width, self.height, self.corner_radius, self.border_width, - self.button_length, self.corner_radius, 1, "w") + requires_recoloring = self.draw_engine.draw_rounded_slider_with_border_and_button(self.width * self.scaling, + self.height * self.scaling, + self.corner_radius * self.scaling, + self.border_width * self.scaling, + self.button_length * self.scaling, + self.corner_radius * self.scaling + , 1, "w") else: - requires_recoloring = self.draw_engine.draw_rounded_slider_with_border_and_button(self.width, self.height, self.corner_radius, self.border_width, - self.button_length, self.corner_radius, 0, "w") + requires_recoloring = self.draw_engine.draw_rounded_slider_with_border_and_button(self.width * self.scaling, + self.height * self.scaling, + self.corner_radius * self.scaling, + self.border_width * self.scaling, + self.button_length * self.scaling, + self.corner_radius * self.scaling, + 0, "w") if no_color_updates is False or requires_recoloring: self.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode)) @@ -145,7 +155,7 @@ class CTkSwitch(CTkBaseClass): bd=0, text=self.text, justify=tkinter.LEFT, - font=self.text_font) + font=self.apply_font_scaling(self.text_font)) self.text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w") self.text_label["anchor"] = "w" if self.textvariable is not None: diff --git a/customtkinter/widgets/widget_base_class.py b/customtkinter/widgets/widget_base_class.py index 796c2cb..738a889 100644 --- a/customtkinter/widgets/widget_base_class.py +++ b/customtkinter/widgets/widget_base_class.py @@ -1,9 +1,13 @@ import tkinter import tkinter.ttk as ttk +import copy +import re from .ctk_tk import CTk from .ctk_toplevel import CTkToplevel from ..appearance_mode_tracker import AppearanceModeTracker +from ..scaling_tracker import ScalingTracker +from ..theme_manager import CTkThemeManager class CTkBaseClass(tkinter.Frame): @@ -12,12 +16,18 @@ class CTkBaseClass(tkinter.Frame): self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color self.width = width # width and height in pixel, represent current size of the widget (not the desired size by init) - self.height = height + self.height = height # width and height are independent of the scale + + # add set_scaling method to callback list of ScalingTracker for automatic scaling changes + ScalingTracker.add_widget(self.set_scaling, self) + self.scaling = ScalingTracker.get_widget_scaling(self) # add set_appearance_mode method to callback list of AppearanceModeTracker for appearance mode changes AppearanceModeTracker.add(self.set_appearance_mode, self) self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark" + super().configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode)) + # overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget too if isinstance(self.master, (tkinter.Tk, tkinter.Toplevel, tkinter.Frame)) and not isinstance(self.master, (CTkBaseClass, CTk, CTkToplevel)): master_old_configure = self.master.config @@ -64,11 +74,11 @@ class CTkBaseClass(tkinter.Frame): if require_redraw: self.draw() - def update_dimensions(self, event): + def update_dimensions_event(self, event): # only redraw if dimensions changed (for performance) - if self.width != event.width or self.height != event.height: - self.width = event.width # adjust current size according to new size given by event - self.height = event.height + if self.width != int(event.width * self.scaling) or self.height != int(event.height * self.scaling): + self.width = int(event.width / self.scaling) # adjust current size according to new size given by event + self.height = int(event.height / self.scaling) # width and height are independent of the scale self.draw(no_color_updates=True) # faster drawing without color changes @@ -104,6 +114,33 @@ class CTkBaseClass(tkinter.Frame): self.draw() + def set_scaling(self, new_scaling): + self.scaling = new_scaling + + super().configure(width=self.width * self.scaling, height=self.height * self.scaling) + + def apply_font_scaling(self, font): + if type(font) == tuple or type(font) == list: + font_list = list(font) + for i in range(len(font_list)): + if (type(font_list[i]) == int or type(font_list[i]) == float) and font_list[i] < 0: + font_list[i] = int(font_list[i] * self.scaling) + return tuple(font_list) + + elif type(font) == str: + for negative_number in re.findall(r" -\d* ", font): + font = font.replace(negative_number, f" {int(int(negative_number) * self.scaling)} ") + return font + + elif isinstance(font, tkinter.font.Font): + new_font_object = copy.copy(font) + if font.cget("size") < 0: + new_font_object.config(size=int(font.cget("size") * self.scaling)) + return new_font_object + + else: + return font + def draw(self, no_color_updates=False): """ abstract of draw method to be overridden """ pass diff --git a/examples/simple_example.py b/examples/simple_example.py index a45e593..cf9583b 100644 --- a/examples/simple_example.py +++ b/examples/simple_example.py @@ -4,6 +4,8 @@ import customtkinter # <- import the CustomTkinter module customtkinter.set_appearance_mode("dark") # Modes: "System" (standard), "Dark", "Light" customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue" +customtkinter.ScalingTracker.set_user_scaling(0.9) + root_tk = customtkinter.CTk() # create CTk window like you do with the Tk window (you can also use normal tkinter.Tk window) root_tk.geometry("400x480") root_tk.title("CustomTkinter Test")