mirror of
https://github.com/TomSchimansky/CustomTkinter.git
synced 2023-08-10 21:13:13 +03:00
finished CTkFont support for button, label, checkbox, created test_font.py
This commit is contained in:
@@ -63,12 +63,16 @@ class CTkButton(CTkBaseClass):
|
||||
|
||||
self._corner_radius = min(self._corner_radius, round(self._current_height/2))
|
||||
|
||||
# text, font, image
|
||||
# text, image
|
||||
self._image = image
|
||||
self._image_label: Union[tkinter.Label, None] = None
|
||||
self._text = text
|
||||
self._text_label: Union[tkinter.Label, None] = None
|
||||
self._font = CTkFont() if font == "default_theme" else self._check_font_type_and_values(font)
|
||||
|
||||
# font
|
||||
self._font = CTkFont() if font == "default_theme" else self._check_font_type(font)
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.add_size_configure_callback(self._update_font)
|
||||
|
||||
# callback and hover functionality
|
||||
self._command = command
|
||||
@@ -120,6 +124,21 @@ class CTkButton(CTkBaseClass):
|
||||
height=self._apply_widget_scaling(self._desired_height))
|
||||
self._draw()
|
||||
|
||||
def _update_font(self):
|
||||
""" pass font to tkinter widgets with applied font scaling and update grid with workaround """
|
||||
if self._text_label is not None:
|
||||
self._text_label.configure(font=self._apply_font_scaling(self._font))
|
||||
|
||||
# Workaround to force grid to be resized when text changes size.
|
||||
# Otherwise grid will lag and only resizes if other mouse action occurs.
|
||||
self._canvas.grid_forget()
|
||||
self._canvas.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="nsew")
|
||||
|
||||
def destroy(self):
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.remove_size_configure_callback(self._update_font)
|
||||
super().destroy()
|
||||
|
||||
def _draw(self, no_color_updates=False):
|
||||
if self._background_corner_colors is not None:
|
||||
self._draw_engine.draw_background_corners(self._apply_widget_scaling(self._current_width),
|
||||
@@ -269,7 +288,12 @@ class CTkButton(CTkBaseClass):
|
||||
self._text_label.configure(text=self._text)
|
||||
|
||||
if "font" in kwargs:
|
||||
self._font = kwargs.pop("font")
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.remove_size_configure_callback(self._update_font)
|
||||
self._font = self._check_font_type(kwargs.pop("font"))
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.add_size_configure_callback(self._update_font)
|
||||
|
||||
if self._text_label is not None:
|
||||
self._text_label.configure(font=self._apply_font_scaling(self._font))
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ from ..theme_manager import ThemeManager
|
||||
from ..settings import Settings
|
||||
from ..draw_engine import DrawEngine
|
||||
from .widget_base_class import CTkBaseClass
|
||||
from ..utility.ctk_font import CTkFont
|
||||
|
||||
|
||||
class CTkCheckBox(CTkBaseClass):
|
||||
@@ -33,7 +34,7 @@ class CTkCheckBox(CTkBaseClass):
|
||||
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme",
|
||||
|
||||
text: str = "CTkCheckBox",
|
||||
font: any = "default_theme",
|
||||
font: Union[tuple, CTkFont] = "default_theme",
|
||||
textvariable: tkinter.Variable = None,
|
||||
state: str = tkinter.NORMAL,
|
||||
hover: bool = True,
|
||||
@@ -65,7 +66,11 @@ class CTkCheckBox(CTkBaseClass):
|
||||
self._text_label: Union[tkinter.Label, None] = None
|
||||
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
|
||||
self._text_color_disabled = ThemeManager.theme["color"]["text_disabled"] if text_color_disabled == "default_theme" else text_color_disabled
|
||||
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
|
||||
|
||||
# font
|
||||
self._font = CTkFont() if font == "default_theme" else self._check_font_type(font)
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.add_size_configure_callback(self._update_font)
|
||||
|
||||
# callback and hover functionality
|
||||
self._command = command
|
||||
@@ -145,10 +150,23 @@ class CTkCheckBox(CTkBaseClass):
|
||||
self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width),
|
||||
height=self._apply_widget_scaling(self._desired_height))
|
||||
|
||||
def _update_font(self):
|
||||
""" pass font to tkinter widgets with applied font scaling and update grid with workaround """
|
||||
if self._text_label is not None:
|
||||
self._text_label.configure(font=self._apply_font_scaling(self._font))
|
||||
|
||||
# Workaround to force grid to be resized when text changes size.
|
||||
# Otherwise grid will lag and only resizes if other mouse action occurs.
|
||||
self._bg_canvas.grid_forget()
|
||||
self._bg_canvas.grid(row=0, column=0, sticky="nswe")
|
||||
|
||||
def destroy(self):
|
||||
if self._variable is not None:
|
||||
self._variable.trace_remove("write", self._variable_callback_name)
|
||||
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.remove_size_configure_callback(self._update_font)
|
||||
|
||||
super().destroy()
|
||||
|
||||
def _draw(self, no_color_updates=False):
|
||||
@@ -212,9 +230,13 @@ class CTkCheckBox(CTkBaseClass):
|
||||
self._text_label.configure(text=self._text)
|
||||
|
||||
if "font" in kwargs:
|
||||
self._font = kwargs.pop("font")
|
||||
if self._text_label is not None:
|
||||
self._text_label.configure(font=self._apply_font_scaling(self._font))
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.remove_size_configure_callback(self._update_font)
|
||||
self._font = self._check_font_type(kwargs.pop("font"))
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.add_size_configure_callback(self._update_font)
|
||||
|
||||
self._update_font()
|
||||
|
||||
if "state" in kwargs:
|
||||
self._state = kwargs.pop("state")
|
||||
|
||||
@@ -5,6 +5,7 @@ from .ctk_canvas import CTkCanvas
|
||||
from ..theme_manager import ThemeManager
|
||||
from ..draw_engine import DrawEngine
|
||||
from .widget_base_class import CTkBaseClass
|
||||
from ..utility.ctk_font import CTkFont
|
||||
|
||||
from customtkinter.utility.utility_functions import pop_from_dict_by_set, check_kwargs_empty
|
||||
|
||||
@@ -30,7 +31,7 @@ class CTkLabel(CTkBaseClass):
|
||||
text_color: Union[str, Tuple[str, str]] = "default_theme",
|
||||
|
||||
text: str = "CTkLabel",
|
||||
font: any = "default_theme",
|
||||
font: Union[tuple, CTkFont] = "default_theme",
|
||||
anchor: str = "center", # label anchor: center, n, e, s, w
|
||||
**kwargs):
|
||||
|
||||
@@ -47,7 +48,11 @@ class CTkLabel(CTkBaseClass):
|
||||
# text
|
||||
self._anchor = anchor
|
||||
self._text = text
|
||||
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
|
||||
|
||||
# font
|
||||
self._font = CTkFont() if font == "default_theme" else self._check_font_type(font)
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.add_size_configure_callback(self._update_font)
|
||||
|
||||
# configure grid system (1x1)
|
||||
self.grid_rowconfigure(0, weight=1)
|
||||
@@ -97,6 +102,20 @@ class CTkLabel(CTkBaseClass):
|
||||
height=self._apply_widget_scaling(self._desired_height))
|
||||
self._draw()
|
||||
|
||||
def _update_font(self):
|
||||
""" pass font to tkinter widgets with applied font scaling and update grid with workaround """
|
||||
self._text_label.configure(font=self._apply_font_scaling(self._font))
|
||||
|
||||
# Workaround to force grid to be resized when text changes size.
|
||||
# Otherwise grid will lag and only resizes if other mouse action occurs.
|
||||
self._canvas.grid_forget()
|
||||
self._canvas.grid(row=0, column=0, sticky="nswe")
|
||||
|
||||
def destroy(self):
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.remove_size_configure_callback(self._update_font)
|
||||
super().destroy()
|
||||
|
||||
def _draw(self, no_color_updates=False):
|
||||
requires_recoloring = self._draw_engine.draw_rounded_rect_with_border(self._apply_widget_scaling(self._current_width),
|
||||
self._apply_widget_scaling(self._current_height),
|
||||
@@ -133,8 +152,13 @@ class CTkLabel(CTkBaseClass):
|
||||
self._text_label.configure(text=self._text)
|
||||
|
||||
if "font" in kwargs:
|
||||
self._font = kwargs.pop("font")
|
||||
self._text_label.configure(font=self._apply_font_scaling(self._font))
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.remove_size_configure_callback(self._update_font)
|
||||
self._font = self._check_font_type(kwargs.pop("font"))
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.add_size_configure_callback(self._update_font)
|
||||
|
||||
self._update_font()
|
||||
|
||||
if "fg_color" in kwargs:
|
||||
self._fg_color = kwargs.pop("fg_color")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import sys
|
||||
import tkinter
|
||||
import tkinter.ttk as ttk
|
||||
import copy
|
||||
@@ -118,7 +119,7 @@ class CTkBaseClass(tkinter.Frame):
|
||||
super().configure(**pop_from_dict_by_set(kwargs, self._valid_tk_frame_attributes)) # configure tkinter.Frame
|
||||
|
||||
# if there are still items in the kwargs dict, raise ValueError
|
||||
self._check_kwargs_empty(kwargs, raise_error=True)
|
||||
check_kwargs_empty(kwargs, raise_error=True)
|
||||
|
||||
if require_redraw:
|
||||
self._draw()
|
||||
@@ -139,10 +140,23 @@ class CTkBaseClass(tkinter.Frame):
|
||||
raise ValueError(f"'{attribute_name}' is not a supported argument. Look at the documentation for supported arguments.")
|
||||
|
||||
@staticmethod
|
||||
def _check_font_type_and_values(font: any):
|
||||
if not isinstance(font, CTkFont):
|
||||
raise ValueError(f"\nFor consistency, Customtkinter requires the font argument {font} to be an instance of CTkFont.\n" +
|
||||
f"\nUsage example: font=customtkinter.CTkFont(family='name', size='size in px')\n(other arguments in the documentation)\n")
|
||||
def _check_font_type(font: any):
|
||||
if isinstance(font, CTkFont):
|
||||
return font
|
||||
|
||||
elif type(font) == tuple and len(font) == 1:
|
||||
sys.stderr.write(f"Warning: font {font} given without size, will be extended with default text size of current theme\n")
|
||||
return font[0], ThemeManager.theme["text"]["size"]
|
||||
|
||||
elif type(font) == tuple and 2 <= len(font) <= 3:
|
||||
return font
|
||||
|
||||
else:
|
||||
raise ValueError(f"Wrong font type {type(font)}\n" +
|
||||
f"For consistency, Customtkinter requires the font argument to be a tuple of len 2 or 3 or an instance of CTkFont.\n" +
|
||||
f"\nUsage example:\n" +
|
||||
f"font=customtkinter.CTkFont(family='<name>', size=<size in px>)\n" +
|
||||
f"font=('<name>', <size in px>)\n")
|
||||
|
||||
def _update_dimensions_event(self, event):
|
||||
# only redraw if dimensions changed (for performance), independent of scaling
|
||||
@@ -219,15 +233,22 @@ class CTkBaseClass(tkinter.Frame):
|
||||
else:
|
||||
return value
|
||||
|
||||
def _apply_font_scaling(self, font: Union[tuple, CTkFont]) -> Union[tuple, CTkFont]:
|
||||
def _apply_font_scaling(self, font: Union[Tuple, CTkFont]) -> tuple:
|
||||
""" Takes CTkFont object and returns tuple font with scaled size, has to be called again for every change of font object """
|
||||
if type(font) == tuple:
|
||||
font_list = list(font)
|
||||
if len(font_list) >= 2 and type(font_list[1]) == int:
|
||||
font_list[1] = int(font_list[1] * self._widget_scaling)
|
||||
return tuple(font_list)
|
||||
if len(font) == 1:
|
||||
return font
|
||||
elif len(font) == 2:
|
||||
return font[0], round(font[1] * self._widget_scaling)
|
||||
elif len(font) == 3:
|
||||
return font[0], round(font[1] * self._widget_scaling), font[2]
|
||||
else:
|
||||
raise ValueError(f"Can not scale font {font}. font needs to be tuple of len 1, 2 or 3")
|
||||
|
||||
elif isinstance(font, CTkFont):
|
||||
return font
|
||||
return font.create_scaled_tuple(self._widget_scaling)
|
||||
else:
|
||||
raise ValueError(f"Can not scale font '{font}' of type {type(font)}. font needs to be tuple or instance of CTkFont")
|
||||
|
||||
def _apply_argument_scaling(self, kwargs: dict) -> dict:
|
||||
scaled_kwargs = copy.copy(kwargs)
|
||||
|
||||
Reference in New Issue
Block a user