mirror of
https://github.com/TomSchimansky/CustomTkinter.git
synced 2023-08-10 21:13:13 +03:00
added CTkFont support to all widgets
This commit is contained in:
parent
25531cdf50
commit
7ea2edeef2
@ -5,9 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
ToDo:
|
ToDo:
|
||||||
- enforce font size in pixel and enforce CTkFont class
|
|
||||||
- complete other theme files
|
- complete other theme files
|
||||||
- auto scaling of images
|
- auto-scaling of images
|
||||||
|
- image tuple for light/dark mode
|
||||||
- change font attribute in wiki
|
- change font attribute in wiki
|
||||||
|
|
||||||
## Unreleased - 2022-10-2
|
## Unreleased - 2022-10-2
|
||||||
@ -18,12 +18,14 @@ ToDo:
|
|||||||
- Added .cget() method to all widgets and windows
|
- Added .cget() method to all widgets and windows
|
||||||
- Added .bind() and .focus() methods to almost all widgets
|
- Added .bind() and .focus() methods to almost all widgets
|
||||||
- Added 'anchor' option to CTkOptionMenu and 'justify' option to CTkComboBox
|
- Added 'anchor' option to CTkOptionMenu and 'justify' option to CTkComboBox
|
||||||
|
- Added CTkFont class
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Changed 'text_font' attribute to 'font' in all widgets, changed 'dropdown_text_font' to 'dropdown_font'
|
- Changed 'text_font' attribute to 'font' in all widgets, changed 'dropdown_text_font' to 'dropdown_font'
|
||||||
- Changed 'dropdown_color' attribute to 'dropdown_fg_color' for combobox, optionmenu
|
- Changed 'dropdown_color' attribute to 'dropdown_fg_color' for combobox, optionmenu
|
||||||
- Changed 'orient' attribute of CTkProgressBar and CTkSlider to 'orientation'
|
- Changed 'orient' attribute of CTkProgressBar and CTkSlider to 'orientation'
|
||||||
- Width and height attributes of CTkCheckBox, CTkRadioButton, CTkSwitch now describe the outer dimensions of the whole widget. The button/switch size is described by separate attributes like checkbox_width, checkbox_height
|
- Width and height attributes of CTkCheckBox, CTkRadioButton, CTkSwitch now describe the outer dimensions of the whole widget. The button/switch size is described by separate attributes like checkbox_width, checkbox_height
|
||||||
|
- font attribute must be tuple or CTkFont now, all size values are measured in pixel now
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- Removed setter and getter functions like set_text in CTkButton
|
- Removed setter and getter functions like set_text in CTkButton
|
||||||
|
@ -293,8 +293,7 @@ class CTkButton(CTkBaseClass):
|
|||||||
if isinstance(self._font, CTkFont):
|
if isinstance(self._font, CTkFont):
|
||||||
self._font.add_size_configure_callback(self._update_font)
|
self._font.add_size_configure_callback(self._update_font)
|
||||||
|
|
||||||
if self._text_label is not None:
|
self._update_font()
|
||||||
self._text_label.configure(font=self._apply_font_scaling(self._font))
|
|
||||||
|
|
||||||
if "state" in kwargs:
|
if "state" in kwargs:
|
||||||
self._state = kwargs.pop("state")
|
self._state = kwargs.pop("state")
|
||||||
|
@ -7,6 +7,7 @@ from ..theme_manager import ThemeManager
|
|||||||
from ..draw_engine import DrawEngine
|
from ..draw_engine import DrawEngine
|
||||||
from .widget_base_class import CTkBaseClass
|
from .widget_base_class import CTkBaseClass
|
||||||
from .dropdown_menu import DropdownMenu
|
from .dropdown_menu import DropdownMenu
|
||||||
|
from ..utility.ctk_font import CTkFont
|
||||||
|
|
||||||
|
|
||||||
class CTkOptionMenu(CTkBaseClass):
|
class CTkOptionMenu(CTkBaseClass):
|
||||||
@ -31,8 +32,8 @@ class CTkOptionMenu(CTkBaseClass):
|
|||||||
dropdown_hover_color: Union[str, Tuple[str, str]] = "default_theme",
|
dropdown_hover_color: Union[str, Tuple[str, str]] = "default_theme",
|
||||||
dropdown_text_color: Union[str, Tuple[str, str]] = "default_theme",
|
dropdown_text_color: Union[str, Tuple[str, str]] = "default_theme",
|
||||||
|
|
||||||
font: any = "default_theme",
|
font: Union[tuple, CTkFont] = "default_theme",
|
||||||
dropdown_font: any = "default_theme",
|
dropdown_font: Union[tuple, CTkFont] = "default_theme",
|
||||||
values: list = None,
|
values: list = None,
|
||||||
variable: tkinter.Variable = None,
|
variable: tkinter.Variable = None,
|
||||||
state: str = tkinter.NORMAL,
|
state: str = tkinter.NORMAL,
|
||||||
@ -56,7 +57,11 @@ class CTkOptionMenu(CTkBaseClass):
|
|||||||
# text and font
|
# text and font
|
||||||
self._text_color = ThemeManager.theme["color"]["text_button"] if text_color == "default_theme" else text_color
|
self._text_color = ThemeManager.theme["color"]["text_button"] if text_color == "default_theme" else text_color
|
||||||
self._text_color_disabled = ThemeManager.theme["color"]["text_button_disabled"] if text_color_disabled == "default_theme" else text_color_disabled
|
self._text_color_disabled = ThemeManager.theme["color"]["text_button_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
|
# callback and hover functionality
|
||||||
self._command = command
|
self._command = command
|
||||||
@ -132,7 +137,7 @@ class CTkOptionMenu(CTkBaseClass):
|
|||||||
self._text_label.configure(text=self._current_value)
|
self._text_label.configure(text=self._current_value)
|
||||||
|
|
||||||
def _create_grid(self):
|
def _create_grid(self):
|
||||||
self._canvas.grid(row=0, column=0, rowspan=1, columnspan=1, sticky="nsew")
|
self._canvas.grid(row=0, column=0, sticky="nsew")
|
||||||
|
|
||||||
left_section_width = self._current_width - self._current_height
|
left_section_width = self._current_width - self._current_height
|
||||||
self._text_label.grid(row=0, column=0, sticky="ew",
|
self._text_label.grid(row=0, column=0, sticky="ew",
|
||||||
@ -156,10 +161,22 @@ class CTkOptionMenu(CTkBaseClass):
|
|||||||
height=self._apply_widget_scaling(self._desired_height))
|
height=self._apply_widget_scaling(self._desired_height))
|
||||||
self._draw()
|
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="nsew")
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
if self._variable is not None: # remove old callback
|
if self._variable is not None: # remove old callback
|
||||||
self._variable.trace_remove("write", self._variable_callback_name)
|
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()
|
super().destroy()
|
||||||
|
|
||||||
def _draw(self, no_color_updates=False):
|
def _draw(self, no_color_updates=False):
|
||||||
@ -232,8 +249,13 @@ class CTkOptionMenu(CTkBaseClass):
|
|||||||
self._dropdown_menu.configure(text_color=kwargs.pop("dropdown_text_color"))
|
self._dropdown_menu.configure(text_color=kwargs.pop("dropdown_text_color"))
|
||||||
|
|
||||||
if "font" in kwargs:
|
if "font" in kwargs:
|
||||||
self._font = kwargs.pop("font")
|
if isinstance(self._font, CTkFont):
|
||||||
self._text_label.configure(font=self._apply_font_scaling(self._font))
|
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 "command" in kwargs:
|
if "command" in kwargs:
|
||||||
self._command = kwargs.pop("command")
|
self._command = kwargs.pop("command")
|
||||||
|
@ -6,6 +6,7 @@ from .ctk_canvas import CTkCanvas
|
|||||||
from ..theme_manager import ThemeManager
|
from ..theme_manager import ThemeManager
|
||||||
from ..draw_engine import DrawEngine
|
from ..draw_engine import DrawEngine
|
||||||
from .widget_base_class import CTkBaseClass
|
from .widget_base_class import CTkBaseClass
|
||||||
|
from ..utility.ctk_font import CTkFont
|
||||||
|
|
||||||
|
|
||||||
class CTkRadioButton(CTkBaseClass):
|
class CTkRadioButton(CTkBaseClass):
|
||||||
@ -32,7 +33,7 @@ class CTkRadioButton(CTkBaseClass):
|
|||||||
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme",
|
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme",
|
||||||
|
|
||||||
text: str = "CTkRadioButton",
|
text: str = "CTkRadioButton",
|
||||||
font: any = "default_theme",
|
font: Union[tuple, CTkFont] = "default_theme",
|
||||||
textvariable: tkinter.Variable = None,
|
textvariable: tkinter.Variable = None,
|
||||||
variable: tkinter.Variable = None,
|
variable: tkinter.Variable = None,
|
||||||
value: Union[int, str] = 0,
|
value: Union[int, str] = 0,
|
||||||
@ -64,7 +65,11 @@ class CTkRadioButton(CTkBaseClass):
|
|||||||
self._text_label: Union[tkinter.Label, None] = None
|
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 = 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._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 control variables
|
# callback and control variables
|
||||||
self._command = command
|
self._command = command
|
||||||
@ -139,10 +144,22 @@ class CTkRadioButton(CTkBaseClass):
|
|||||||
self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width),
|
self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width),
|
||||||
height=self._apply_widget_scaling(self._desired_height))
|
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 """
|
||||||
|
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, columnspan=3, sticky="nswe")
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
if self._variable is not None:
|
if self._variable is not None:
|
||||||
self._variable.trace_remove("write", self._variable_callback_name)
|
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()
|
super().destroy()
|
||||||
|
|
||||||
def _draw(self, no_color_updates=False):
|
def _draw(self, no_color_updates=False):
|
||||||
@ -191,8 +208,13 @@ class CTkRadioButton(CTkBaseClass):
|
|||||||
self._text_label.configure(text=self._text)
|
self._text_label.configure(text=self._text)
|
||||||
|
|
||||||
if "font" in kwargs:
|
if "font" in kwargs:
|
||||||
self._font = kwargs.pop("font")
|
if isinstance(self._font, CTkFont):
|
||||||
self._text_label.configure(font=self._apply_font_scaling(self._font))
|
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:
|
if "state" in kwargs:
|
||||||
self._state = kwargs.pop("state")
|
self._state = kwargs.pop("state")
|
||||||
|
@ -6,6 +6,7 @@ from .ctk_canvas import CTkCanvas
|
|||||||
from ..theme_manager import ThemeManager
|
from ..theme_manager import ThemeManager
|
||||||
from ..draw_engine import DrawEngine
|
from ..draw_engine import DrawEngine
|
||||||
from .widget_base_class import CTkBaseClass
|
from .widget_base_class import CTkBaseClass
|
||||||
|
from ..utility.ctk_font import CTkFont
|
||||||
|
|
||||||
|
|
||||||
class CTkSwitch(CTkBaseClass):
|
class CTkSwitch(CTkBaseClass):
|
||||||
@ -34,7 +35,7 @@ class CTkSwitch(CTkBaseClass):
|
|||||||
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme",
|
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme",
|
||||||
|
|
||||||
text: str = "CTkSwitch",
|
text: str = "CTkSwitch",
|
||||||
font: any = "default_theme",
|
font: Union[tuple, CTkFont] = "default_theme",
|
||||||
textvariable: tkinter.Variable = None,
|
textvariable: tkinter.Variable = None,
|
||||||
onvalue: Union[int, str] = 1,
|
onvalue: Union[int, str] = 1,
|
||||||
offvalue: Union[int, str] = 0,
|
offvalue: Union[int, str] = 0,
|
||||||
@ -63,7 +64,11 @@ class CTkSwitch(CTkBaseClass):
|
|||||||
# text
|
# text
|
||||||
self._text = text
|
self._text = text
|
||||||
self._text_label = None
|
self._text_label = None
|
||||||
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)
|
||||||
|
|
||||||
# shape
|
# shape
|
||||||
self._corner_radius = ThemeManager.theme["shape"]["switch_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
self._corner_radius = ThemeManager.theme["shape"]["switch_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||||
@ -146,11 +151,23 @@ class CTkSwitch(CTkBaseClass):
|
|||||||
self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width),
|
self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width),
|
||||||
height=self._apply_widget_scaling(self._desired_height))
|
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 """
|
||||||
|
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, columnspan=3, sticky="nswe")
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
# remove variable_callback from variable callbacks if variable exists
|
# remove variable_callback from variable callbacks if variable exists
|
||||||
if self._variable is not None:
|
if self._variable is not None:
|
||||||
self._variable.trace_remove("write", self._variable_callback_name)
|
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()
|
super().destroy()
|
||||||
|
|
||||||
def _set_cursor(self):
|
def _set_cursor(self):
|
||||||
@ -241,8 +258,13 @@ class CTkSwitch(CTkBaseClass):
|
|||||||
self._text_label.configure(text=self._text)
|
self._text_label.configure(text=self._text)
|
||||||
|
|
||||||
if "font" in kwargs:
|
if "font" in kwargs:
|
||||||
self._font = kwargs.pop("font")
|
if isinstance(self._font, CTkFont):
|
||||||
self._text_label.configure(font=self._apply_font_scaling(self._font))
|
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:
|
if "state" in kwargs:
|
||||||
self._state = kwargs.pop("state")
|
self._state = kwargs.pop("state")
|
||||||
|
@ -6,6 +6,7 @@ from .ctk_scrollbar import CTkScrollbar
|
|||||||
from ..theme_manager import ThemeManager
|
from ..theme_manager import ThemeManager
|
||||||
from ..draw_engine import DrawEngine
|
from ..draw_engine import DrawEngine
|
||||||
from .widget_base_class import CTkBaseClass
|
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
|
from customtkinter.utility.utility_functions import pop_from_dict_by_set, check_kwargs_empty
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ class CTkTextbox(CTkBaseClass):
|
|||||||
scrollbar_color: Union[str, Tuple[str, str]] = "default_theme",
|
scrollbar_color: Union[str, Tuple[str, str]] = "default_theme",
|
||||||
scrollbar_hover_color: Union[str, Tuple[str, str]] = "default_theme",
|
scrollbar_hover_color: Union[str, Tuple[str, str]] = "default_theme",
|
||||||
|
|
||||||
font: any = "default_theme",
|
font: Union[tuple, CTkFont] = "default_theme",
|
||||||
activate_scrollbars: bool = True,
|
activate_scrollbars: bool = True,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
|
|
||||||
@ -65,14 +66,16 @@ class CTkTextbox(CTkBaseClass):
|
|||||||
self._border_width = ThemeManager.theme["shape"]["frame_border_width"] if border_width == "default_theme" else border_width
|
self._border_width = ThemeManager.theme["shape"]["frame_border_width"] if border_width == "default_theme" else border_width
|
||||||
self._border_spacing = border_spacing
|
self._border_spacing = border_spacing
|
||||||
|
|
||||||
# text
|
# font
|
||||||
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else 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)
|
||||||
|
|
||||||
self._canvas = CTkCanvas(master=self,
|
self._canvas = CTkCanvas(master=self,
|
||||||
highlightthickness=0,
|
highlightthickness=0,
|
||||||
width=self._apply_widget_scaling(self._current_width),
|
width=self._apply_widget_scaling(self._current_width),
|
||||||
height=self._apply_widget_scaling(self._current_height))
|
height=self._apply_widget_scaling(self._current_height))
|
||||||
self._canvas.grid(row=0, column=0, padx=0, pady=0, rowspan=2, columnspan=2, sticky="nsew")
|
self._canvas.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="nsew")
|
||||||
self._canvas.configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode))
|
self._canvas.configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode))
|
||||||
self._draw_engine = DrawEngine(self._canvas)
|
self._draw_engine = DrawEngine(self._canvas)
|
||||||
|
|
||||||
@ -191,6 +194,21 @@ class CTkTextbox(CTkBaseClass):
|
|||||||
height=self._apply_widget_scaling(self._desired_height))
|
height=self._apply_widget_scaling(self._desired_height))
|
||||||
self._draw()
|
self._draw()
|
||||||
|
|
||||||
|
def _update_font(self):
|
||||||
|
""" pass font to tkinter widgets with applied font scaling and update grid with workaround """
|
||||||
|
self._textbox.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):
|
def _draw(self, no_color_updates=False):
|
||||||
|
|
||||||
if not self._canvas.winfo_exists():
|
if not self._canvas.winfo_exists():
|
||||||
@ -267,8 +285,13 @@ class CTkTextbox(CTkBaseClass):
|
|||||||
require_redraw = True
|
require_redraw = True
|
||||||
|
|
||||||
if "font" in kwargs:
|
if "font" in kwargs:
|
||||||
self._font = kwargs.pop("font")
|
if isinstance(self._font, CTkFont):
|
||||||
self._textbox.configure(font=self._apply_font_scaling(self._font))
|
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()
|
||||||
|
|
||||||
self._textbox.configure(**pop_from_dict_by_set(kwargs, self._valid_tk_text_attributes))
|
self._textbox.configure(**pop_from_dict_by_set(kwargs, self._valid_tk_text_attributes))
|
||||||
super().configure(require_redraw=require_redraw, **kwargs)
|
super().configure(require_redraw=require_redraw, **kwargs)
|
||||||
|
@ -7,6 +7,7 @@ from typing import Union, Tuple, Callable, List
|
|||||||
from ..theme_manager import ThemeManager
|
from ..theme_manager import ThemeManager
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
from ..scaling_tracker import ScalingTracker
|
from ..scaling_tracker import ScalingTracker
|
||||||
|
from ..utility.ctk_font import CTkFont
|
||||||
|
|
||||||
|
|
||||||
class DropdownMenu(tkinter.Menu):
|
class DropdownMenu(tkinter.Menu):
|
||||||
@ -17,7 +18,7 @@ class DropdownMenu(tkinter.Menu):
|
|||||||
hover_color: Union[str, Tuple[str, str]] = "default_theme",
|
hover_color: Union[str, Tuple[str, str]] = "default_theme",
|
||||||
text_color: Union[str, Tuple[str, str]] = "default_theme",
|
text_color: Union[str, Tuple[str, str]] = "default_theme",
|
||||||
|
|
||||||
font: Union[str, Tuple[str, str]] = "default_theme",
|
font: Union[tuple, CTkFont] = "default_theme",
|
||||||
command: Callable = None,
|
command: Callable = None,
|
||||||
values: List[str] = None,
|
values: List[str] = None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
@ -35,7 +36,11 @@ class DropdownMenu(tkinter.Menu):
|
|||||||
self._fg_color = ThemeManager.theme["color"]["dropdown_color"] if fg_color == "default_theme" else fg_color
|
self._fg_color = ThemeManager.theme["color"]["dropdown_color"] if fg_color == "default_theme" else fg_color
|
||||||
self._hover_color = ThemeManager.theme["color"]["dropdown_hover"] if hover_color == "default_theme" else hover_color
|
self._hover_color = ThemeManager.theme["color"]["dropdown_hover"] if hover_color == "default_theme" else hover_color
|
||||||
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
|
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
|
||||||
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)
|
||||||
|
|
||||||
self._configure_menu_for_platforms()
|
self._configure_menu_for_platforms()
|
||||||
|
|
||||||
@ -44,6 +49,15 @@ class DropdownMenu(tkinter.Menu):
|
|||||||
|
|
||||||
self._add_menu_commands()
|
self._add_menu_commands()
|
||||||
|
|
||||||
|
def _update_font(self):
|
||||||
|
""" pass font to tkinter widgets with applied font scaling """
|
||||||
|
super().configure(font=self._apply_font_scaling(self._font))
|
||||||
|
|
||||||
|
def destroy(self):
|
||||||
|
if isinstance(self._font, CTkFont):
|
||||||
|
self._font.remove_size_configure_callback(self._update_font)
|
||||||
|
super().destroy()
|
||||||
|
|
||||||
def _configure_menu_for_platforms(self):
|
def _configure_menu_for_platforms(self):
|
||||||
""" apply platform specific appearance attributes, configure all colors """
|
""" apply platform specific appearance attributes, configure all colors """
|
||||||
|
|
||||||
@ -120,8 +134,13 @@ class DropdownMenu(tkinter.Menu):
|
|||||||
super().configure(fg=ThemeManager.single_color(self._text_color, self._appearance_mode))
|
super().configure(fg=ThemeManager.single_color(self._text_color, self._appearance_mode))
|
||||||
|
|
||||||
if "font" in kwargs:
|
if "font" in kwargs:
|
||||||
self._font = kwargs.pop("font")
|
if isinstance(self._font, CTkFont):
|
||||||
super().configure(font=self._apply_font_scaling(self._font))
|
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 "command" in kwargs:
|
if "command" in kwargs:
|
||||||
self._command = kwargs.pop("command")
|
self._command = kwargs.pop("command")
|
||||||
@ -159,27 +178,41 @@ class DropdownMenu(tkinter.Menu):
|
|||||||
else:
|
else:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def _apply_font_scaling(self, font):
|
def _apply_font_scaling(self, font: Union[Tuple, CTkFont]) -> tuple:
|
||||||
if type(font) == tuple or type(font) == list:
|
""" Takes CTkFont object and returns tuple font with scaled size, has to be called again for every change of font object """
|
||||||
font_list = list(font)
|
if type(font) == tuple:
|
||||||
for i in range(len(font_list)):
|
if len(font) == 1:
|
||||||
if (type(font_list[i]) == int or type(font_list[i]) == float) and font_list[i] < 0:
|
return font
|
||||||
font_list[i] = int(font_list[i] * self._widget_scaling)
|
elif len(font) == 2:
|
||||||
return tuple(font_list)
|
return font[0], -abs(round(font[1] * self._widget_scaling))
|
||||||
|
elif len(font) == 3:
|
||||||
|
return font[0], -abs(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 type(font) == str:
|
elif isinstance(font, CTkFont):
|
||||||
for negative_number in re.findall(r" -\d* ", font):
|
return font.create_scaled_tuple(self._widget_scaling)
|
||||||
font = font.replace(negative_number, f" {int(int(negative_number) * 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")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _check_font_type(font: any):
|
||||||
|
if isinstance(font, CTkFont):
|
||||||
return font
|
return font
|
||||||
|
|
||||||
elif isinstance(font, tkinter.font.Font):
|
elif type(font) == tuple and len(font) == 1:
|
||||||
new_font_object = copy.copy(font)
|
sys.stderr.write(f"Warning: font {font} given without size, will be extended with default text size of current theme\n")
|
||||||
if font.cget("size") < 0:
|
return font[0], ThemeManager.theme["text"]["size"]
|
||||||
new_font_object.config(size=int(font.cget("size") * self._widget_scaling))
|
|
||||||
return new_font_object
|
elif type(font) == tuple and 2 <= len(font) <= 3:
|
||||||
|
return font
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return font
|
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 _set_scaling(self, new_widget_scaling, new_spacing_scaling, new_window_scaling):
|
def _set_scaling(self, new_widget_scaling, new_spacing_scaling, new_window_scaling):
|
||||||
self._widget_scaling = new_widget_scaling
|
self._widget_scaling = new_widget_scaling
|
||||||
|
@ -56,12 +56,25 @@ for i in range(30):
|
|||||||
b.grid(row=i, column=1, pady=1)
|
b.grid(row=i, column=1, pady=1)
|
||||||
c = customtkinter.CTkCheckBox(frame_2, font=label_font)
|
c = customtkinter.CTkCheckBox(frame_2, font=label_font)
|
||||||
c.grid(row=i, column=2, pady=1)
|
c.grid(row=i, column=2, pady=1)
|
||||||
c = customtkinter.CTkComboBox(frame_2, font=label_font, height=15)
|
c = customtkinter.CTkComboBox(frame_2, font=label_font, dropdown_font=label_font, height=15)
|
||||||
c.grid(row=i, column=3, pady=1)
|
c.grid(row=i, column=3, pady=1)
|
||||||
e = customtkinter.CTkEntry(frame_2, font=label_font, height=15, placeholder_text="testtest")
|
e = customtkinter.CTkEntry(frame_2, font=label_font, height=15, placeholder_text="testtest")
|
||||||
e.grid(row=i, column=4, pady=1)
|
e.grid(row=i, column=4, pady=1)
|
||||||
|
o = customtkinter.CTkOptionMenu(frame_2, font=label_font, height=15, width=50)
|
||||||
|
o.grid(row=i, column=5, pady=1)
|
||||||
|
r = customtkinter.CTkRadioButton(frame_2, font=label_font, height=15, width=50)
|
||||||
|
r.grid(row=i, column=6, pady=1)
|
||||||
|
s = customtkinter.CTkSwitch(frame_2, font=label_font, height=15, width=50)
|
||||||
|
s.grid(row=i, column=7, pady=1)
|
||||||
frame_2.grid_columnconfigure((0, 1, 2, 3, 4), weight=1)
|
frame_2.grid_columnconfigure((0, 1, 2, 3, 4), weight=1)
|
||||||
|
|
||||||
app.after(1500, lambda: label_font.configure(size=10))
|
def change_font():
|
||||||
# app.after(1500, lambda: l.configure(text="dshgfldjskhfjdslafhdjsgkkjdaslö"))
|
import time
|
||||||
|
t1 = time.perf_counter()
|
||||||
|
label_font.configure(size=10, overstrike=True)
|
||||||
|
t2 = time.perf_counter()
|
||||||
|
print("change_font:", (t2-t1)*1000, "ms")
|
||||||
|
|
||||||
|
app.after(3000, change_font)
|
||||||
|
app.after(6000, lambda: label_font.configure(size=8, overstrike=False))
|
||||||
app.mainloop()
|
app.mainloop()
|
||||||
|
Loading…
Reference in New Issue
Block a user