From 03249110f3263024bb5365b8a9010cf179ebbb6d Mon Sep 17 00:00:00 2001 From: Tom Schimansky Date: Tue, 29 Nov 2022 19:06:33 +0100 Subject: [PATCH] restructured imports from modules, created imports in __init__.py --- customtkinter/__init__.py | 93 ++++++------------- customtkinter/utility/__init__.py | 0 customtkinter/windows/__init__.py | 3 + customtkinter/windows/ctk_input_dialog.py | 8 +- customtkinter/windows/ctk_tk.py | 8 +- customtkinter/windows/ctk_toplevel.py | 8 +- customtkinter/windows/widgets/__init__.py | 18 +++- .../widgets/appearance_mode/__init__.py | 4 + .../widgets/core_rendering/__init__.py | 10 ++ .../widgets/core_rendering/draw_engine.py | 2 +- .../widgets/core_widget_classes/__init__.py | 2 + ...widget_base_class.py => ctk_base_class.py} | 23 +++-- .../core_widget_classes/dropdown_menu.py | 8 +- customtkinter/windows/widgets/ctk_button.py | 12 +-- customtkinter/windows/widgets/ctk_checkbox.py | 10 +- customtkinter/windows/widgets/ctk_combobox.py | 12 +-- customtkinter/windows/widgets/ctk_entry.py | 13 ++- customtkinter/windows/widgets/ctk_frame.py | 8 +- customtkinter/windows/widgets/ctk_label.py | 15 ++- .../windows/widgets/ctk_optionmenu.py | 12 +-- .../windows/widgets/ctk_progressbar.py | 8 +- .../windows/widgets/ctk_radiobutton.py | 10 +- .../windows/widgets/ctk_scrollbar.py | 8 +- .../windows/widgets/ctk_segmented_button.py | 4 +- customtkinter/windows/widgets/ctk_slider.py | 8 +- customtkinter/windows/widgets/ctk_switch.py | 10 +- customtkinter/windows/widgets/ctk_tabview.py | 8 +- customtkinter/windows/widgets/ctk_textbox.py | 13 ++- .../windows/widgets/font/__init__.py | 24 +++++ .../windows/widgets/font/ctk_font.py | 2 +- .../windows/widgets/image/__init__.py | 1 + .../windows/widgets/scaling/__init__.py | 7 ++ .../widgets/scaling/scaling_base_class.py | 2 +- .../windows/widgets/theme/__init__.py | 9 ++ .../windows/widgets/utility/__init__.py | 1 + .../widgets}/utility/utility_functions.py | 1 - examples/complex_example.py | 21 ++--- test/unit_tests/test_ctk.py | 6 +- 38 files changed, 226 insertions(+), 186 deletions(-) delete mode 100644 customtkinter/utility/__init__.py rename customtkinter/windows/widgets/core_widget_classes/{widget_base_class.py => ctk_base_class.py} (95%) create mode 100644 customtkinter/windows/widgets/utility/__init__.py rename customtkinter/{ => windows/widgets}/utility/utility_functions.py (99%) diff --git a/customtkinter/__init__.py b/customtkinter/__init__.py index 696ab26..df5dae0 100644 --- a/customtkinter/__init__.py +++ b/customtkinter/__init__.py @@ -6,77 +6,42 @@ from tkinter import Variable, StringVar, IntVar, DoubleVar, BooleanVar from tkinter.constants import * import tkinter.filedialog as filedialog -_ = Variable, StringVar, IntVar, DoubleVar, BooleanVar, CENTER, filedialog # prevent IDE from removing unused imports - # import manager classes -from .windows.widgets.appearance_mode.appearance_mode_tracker import AppearanceModeTracker -from .windows.widgets.font.font_manager import FontManager -from .windows.widgets.scaling.scaling_tracker import ScalingTracker -from .windows.widgets.theme.theme_manager import ThemeManager -from .windows.widgets.core_rendering.draw_engine import DrawEngine - -AppearanceModeTracker.init_appearance_mode() - -# load default blue theme -try: - ThemeManager.load_theme("blue") -except FileNotFoundError as err: - raise FileNotFoundError(f"{err}\n\nThe .json theme file for CustomTkinter could not be found.\n" + - f"If packaging with pyinstaller was used, have a look at the wiki:\n" + - f"https://github.com/TomSchimansky/CustomTkinter/wiki/Packaging#windows-pyinstaller-auto-py-to-exe") - -FontManager.init_font_manager() - -# determine draw method based on current platform -if sys.platform == "darwin": - DrawEngine.preferred_drawing_method = "polygon_shapes" -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")) -FontManager.load_font(os.path.join(script_directory, "assets", "fonts", "Roboto", "Roboto-Medium.ttf")) - -# load font necessary for rendering the widgets (used on Windows/Linux) -if FontManager.load_font(os.path.join(script_directory, "assets", "fonts", "CustomTkinter_shapes_font.otf")) is False: - # change draw method if font loading failed - if DrawEngine.preferred_drawing_method == "font_shapes": - sys.stderr.write("customtkinter.__init__ warning: " + - "Preferred drawing method 'font_shapes' can not be used because the font file could not be loaded.\n" + - "Using 'circle_shapes' instead. The rendering quality will be bad!\n") - DrawEngine.preferred_drawing_method = "circle_shapes" +from .windows.widgets.appearance_mode import AppearanceModeTracker +from .windows.widgets.font import FontManager +from .windows.widgets.scaling import ScalingTracker +from .windows.widgets.theme import ThemeManager +from .windows.widgets.core_rendering import DrawEngine # import widgets -from .windows.widgets.ctk_button import CTkButton -from .windows.widgets.ctk_checkbox import CTkCheckBox -from .windows.widgets.ctk_combobox import CTkComboBox -from .windows.widgets.ctk_entry import CTkEntry -from .windows.widgets.ctk_frame import CTkFrame -from .windows.widgets.ctk_label import CTkLabel -from .windows.widgets.ctk_optionmenu import CTkOptionMenu -from .windows.widgets.ctk_progressbar import CTkProgressBar -from .windows.widgets.ctk_radiobutton import CTkRadioButton -from .windows.widgets.ctk_scrollbar import CTkScrollbar -from .windows.widgets.ctk_segmented_button import CTkSegmentedButton -from .windows.widgets.ctk_slider import CTkSlider -from .windows.widgets.ctk_switch import CTkSwitch -from .windows.widgets.ctk_tabview import CTkTabview -from .windows.widgets.ctk_textbox import CTkTextbox +from .windows.widgets import CTkButton +from .windows.widgets import CTkCheckBox +from .windows.widgets import CTkComboBox +from .windows.widgets import CTkEntry +from .windows.widgets import CTkFrame +from .windows.widgets import CTkLabel +from .windows.widgets import CTkOptionMenu +from .windows.widgets import CTkProgressBar +from .windows.widgets import CTkRadioButton +from .windows.widgets import CTkScrollbar +from .windows.widgets import CTkSegmentedButton +from .windows.widgets import CTkSlider +from .windows.widgets import CTkSwitch +from .windows.widgets import CTkTabview +from .windows.widgets import CTkTextbox # import windows -from .windows.ctk_tk import CTk -from .windows.ctk_toplevel import CTkToplevel -from .windows.ctk_input_dialog import CTkInputDialog +from .windows import CTk +from .windows import CTkToplevel +from .windows import CTkInputDialog -# font classes -from .windows.widgets.font.ctk_font import CTkFont +# import font classes +from .windows.widgets.font import CTkFont -# image classes -from .windows.widgets.image.ctk_image import CTkImage +# import image classes +from .windows.widgets.image import CTkImage + +_ = Variable, StringVar, IntVar, DoubleVar, BooleanVar, CENTER, filedialog # prevent IDE from removing unused imports def set_appearance_mode(mode_string: str): diff --git a/customtkinter/utility/__init__.py b/customtkinter/utility/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/customtkinter/windows/__init__.py b/customtkinter/windows/__init__.py index e69de29..ca681b7 100644 --- a/customtkinter/windows/__init__.py +++ b/customtkinter/windows/__init__.py @@ -0,0 +1,3 @@ +from .ctk_tk import CTk +from .ctk_toplevel import CTkToplevel +from .ctk_input_dialog import CTkInputDialog diff --git a/customtkinter/windows/ctk_input_dialog.py b/customtkinter/windows/ctk_input_dialog.py index 09bbcb7..fc37527 100644 --- a/customtkinter/windows/ctk_input_dialog.py +++ b/customtkinter/windows/ctk_input_dialog.py @@ -1,9 +1,9 @@ from typing import Union, Tuple, Optional -from .widgets.ctk_label import CTkLabel -from .widgets.ctk_entry import CTkEntry -from .widgets.ctk_button import CTkButton -from .widgets.theme.theme_manager import ThemeManager +from .widgets import CTkLabel +from .widgets import CTkEntry +from .widgets import CTkButton +from .widgets.theme import ThemeManager from .ctk_toplevel import CTkToplevel diff --git a/customtkinter/windows/ctk_tk.py b/customtkinter/windows/ctk_tk.py index f377018..2371997 100644 --- a/customtkinter/windows/ctk_tk.py +++ b/customtkinter/windows/ctk_tk.py @@ -6,11 +6,11 @@ import platform import ctypes from typing import Union, Tuple, Optional -from .widgets.theme.theme_manager import ThemeManager -from .widgets.scaling.scaling_base_class import CTkScalingBaseClass -from .widgets.appearance_mode.appearance_mode_base_class import CTkAppearanceModeBaseClass +from .widgets.theme import ThemeManager +from .widgets.scaling import CTkScalingBaseClass +from .widgets.appearance_mode import CTkAppearanceModeBaseClass -from ..utility.utility_functions import pop_from_dict_by_set, check_kwargs_empty +from customtkinter.windows.widgets.utility.utility_functions import pop_from_dict_by_set, check_kwargs_empty class CTk(tkinter.Tk, CTkAppearanceModeBaseClass, CTkScalingBaseClass): diff --git a/customtkinter/windows/ctk_toplevel.py b/customtkinter/windows/ctk_toplevel.py index 46179b3..4e43839 100644 --- a/customtkinter/windows/ctk_toplevel.py +++ b/customtkinter/windows/ctk_toplevel.py @@ -6,11 +6,11 @@ import platform import ctypes from typing import Union, Tuple, Optional -from .widgets.theme.theme_manager import ThemeManager -from .widgets.scaling.scaling_base_class import CTkScalingBaseClass -from .widgets.appearance_mode.appearance_mode_base_class import CTkAppearanceModeBaseClass +from .widgets.theme import ThemeManager +from .widgets.scaling import CTkScalingBaseClass +from .widgets.appearance_mode import CTkAppearanceModeBaseClass -from ..utility.utility_functions import pop_from_dict_by_set, check_kwargs_empty +from customtkinter.windows.widgets.utility.utility_functions import pop_from_dict_by_set, check_kwargs_empty class CTkToplevel(tkinter.Toplevel, CTkAppearanceModeBaseClass, CTkScalingBaseClass): diff --git a/customtkinter/windows/widgets/__init__.py b/customtkinter/windows/widgets/__init__.py index 7b8ad04..6da9aec 100644 --- a/customtkinter/windows/widgets/__init__.py +++ b/customtkinter/windows/widgets/__init__.py @@ -1,3 +1,19 @@ -from customtkinter.windows.widgets.core_rendering.ctk_canvas import CTkCanvas +from .ctk_button import CTkButton +from .ctk_checkbox import CTkCheckBox +from .ctk_combobox import CTkComboBox +from .ctk_entry import CTkEntry +from .ctk_frame import CTkFrame +from .ctk_label import CTkLabel +from .ctk_optionmenu import CTkOptionMenu +from .ctk_progressbar import CTkProgressBar +from .ctk_radiobutton import CTkRadioButton +from .ctk_scrollbar import CTkScrollbar +from .ctk_segmented_button import CTkSegmentedButton +from .ctk_slider import CTkSlider +from .ctk_switch import CTkSwitch +from .ctk_tabview import CTkTabview +from .ctk_textbox import CTkTextbox +# init canvas font character map for current platform +from .core_rendering import CTkCanvas CTkCanvas.init_font_character_mapping() diff --git a/customtkinter/windows/widgets/appearance_mode/__init__.py b/customtkinter/windows/widgets/appearance_mode/__init__.py index e69de29..e979ca8 100644 --- a/customtkinter/windows/widgets/appearance_mode/__init__.py +++ b/customtkinter/windows/widgets/appearance_mode/__init__.py @@ -0,0 +1,4 @@ +from .appearance_mode_base_class import CTkAppearanceModeBaseClass +from .appearance_mode_tracker import AppearanceModeTracker + +AppearanceModeTracker.init_appearance_mode() diff --git a/customtkinter/windows/widgets/core_rendering/__init__.py b/customtkinter/windows/widgets/core_rendering/__init__.py index e69de29..571adc7 100644 --- a/customtkinter/windows/widgets/core_rendering/__init__.py +++ b/customtkinter/windows/widgets/core_rendering/__init__.py @@ -0,0 +1,10 @@ +import sys + +from .ctk_canvas import CTkCanvas +from .draw_engine import DrawEngine + +# determine draw method based on current platform +if sys.platform == "darwin": + DrawEngine.preferred_drawing_method = "polygon_shapes" +else: + DrawEngine.preferred_drawing_method = "font_shapes" diff --git a/customtkinter/windows/widgets/core_rendering/draw_engine.py b/customtkinter/windows/widgets/core_rendering/draw_engine.py index 4c0a336..5acea56 100644 --- a/customtkinter/windows/widgets/core_rendering/draw_engine.py +++ b/customtkinter/windows/widgets/core_rendering/draw_engine.py @@ -5,7 +5,7 @@ import tkinter from typing import Union, TYPE_CHECKING if TYPE_CHECKING: - from customtkinter.windows.widgets.core_rendering.ctk_canvas import CTkCanvas + from ..core_rendering import CTkCanvas class DrawEngine: diff --git a/customtkinter/windows/widgets/core_widget_classes/__init__.py b/customtkinter/windows/widgets/core_widget_classes/__init__.py index e69de29..75e2d84 100644 --- a/customtkinter/windows/widgets/core_widget_classes/__init__.py +++ b/customtkinter/windows/widgets/core_widget_classes/__init__.py @@ -0,0 +1,2 @@ +from .dropdown_menu import DropdownMenu +from .ctk_base_class import CTkBaseClass diff --git a/customtkinter/windows/widgets/core_widget_classes/widget_base_class.py b/customtkinter/windows/widgets/core_widget_classes/ctk_base_class.py similarity index 95% rename from customtkinter/windows/widgets/core_widget_classes/widget_base_class.py rename to customtkinter/windows/widgets/core_widget_classes/ctk_base_class.py index c746341..c2331d5 100644 --- a/customtkinter/windows/widgets/core_widget_classes/widget_base_class.py +++ b/customtkinter/windows/widgets/core_widget_classes/ctk_base_class.py @@ -8,15 +8,18 @@ try: except ImportError: from typing_extensions import TypedDict -from ...ctk_tk import CTk -from ...ctk_toplevel import CTkToplevel -from ..theme.theme_manager import ThemeManager -from ..font.ctk_font import CTkFont -from ..image.ctk_image import CTkImage -from ..appearance_mode.appearance_mode_base_class import CTkAppearanceModeBaseClass -from ..scaling.scaling_base_class import CTkScalingBaseClass +# removed due to circular import +# from ...ctk_tk import CTk +# from ...ctk_toplevel import CTkToplevel +from .... import windows # import windows for isinstance checks -from ....utility.utility_functions import pop_from_dict_by_set, check_kwargs_empty +from ..theme import ThemeManager +from ..font import CTkFont +from ..image import CTkImage +from ..appearance_mode import CTkAppearanceModeBaseClass +from ..scaling import CTkScalingBaseClass + +from ..utility import pop_from_dict_by_set, check_kwargs_empty class CTkBaseClass(tkinter.Frame, CTkAppearanceModeBaseClass, CTkScalingBaseClass): @@ -70,7 +73,7 @@ class CTkBaseClass(tkinter.Frame, CTkAppearanceModeBaseClass, CTkScalingBaseClas super().bind('', self._update_dimensions_event) # overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget as well - if isinstance(self.master, (tkinter.Tk, tkinter.Toplevel, tkinter.Frame)) and not isinstance(self.master, (CTkBaseClass, CTk, CTkToplevel)): + if isinstance(self.master, (tkinter.Tk, tkinter.Toplevel, tkinter.Frame, tkinter.LabelFrame, ttk.Frame, ttk.LabelFrame, ttk.Notebook)) and not isinstance(self.master, CTkBaseClass): master_old_configure = self.master.config def new_configure(*args, **kwargs): @@ -193,7 +196,7 @@ class CTkBaseClass(tkinter.Frame, CTkAppearanceModeBaseClass, CTkScalingBaseClas if master_widget is None: master_widget = self.master - if isinstance(master_widget, (CTkBaseClass, CTk, CTkToplevel)): + if isinstance(master_widget, (windows.widgets.core_widget_classes.CTkBaseClass, windows.CTk, windows.CTkToplevel)): if master_widget.cget("fg_color") is not None and master_widget.cget("fg_color") != "transparent": return master_widget.cget("fg_color") diff --git a/customtkinter/windows/widgets/core_widget_classes/dropdown_menu.py b/customtkinter/windows/widgets/core_widget_classes/dropdown_menu.py index e8082ae..a6b8186 100644 --- a/customtkinter/windows/widgets/core_widget_classes/dropdown_menu.py +++ b/customtkinter/windows/widgets/core_widget_classes/dropdown_menu.py @@ -2,10 +2,10 @@ import tkinter import sys from typing import Union, Tuple, Callable, List, Optional -from ..theme.theme_manager import ThemeManager -from ..font.ctk_font import CTkFont -from ..appearance_mode.appearance_mode_base_class import CTkAppearanceModeBaseClass -from ..scaling.scaling_base_class import CTkScalingBaseClass +from ..theme import ThemeManager +from ..font import CTkFont +from ..appearance_mode import CTkAppearanceModeBaseClass +from ..scaling import CTkScalingBaseClass class DropdownMenu(tkinter.Menu, CTkAppearanceModeBaseClass, CTkScalingBaseClass): diff --git a/customtkinter/windows/widgets/ctk_button.py b/customtkinter/windows/widgets/ctk_button.py index 815d652..3865c4e 100644 --- a/customtkinter/windows/widgets/ctk_button.py +++ b/customtkinter/windows/widgets/ctk_button.py @@ -2,12 +2,12 @@ import tkinter import sys from typing import Union, Tuple, Callable, Optional -from .core_rendering.ctk_canvas import CTkCanvas -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass -from .font.ctk_font import CTkFont -from .image.ctk_image import CTkImage +from .core_rendering import CTkCanvas +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass +from .font import CTkFont +from .image import CTkImage class CTkButton(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_checkbox.py b/customtkinter/windows/widgets/ctk_checkbox.py index 40a1db4..fb8a7e2 100644 --- a/customtkinter/windows/widgets/ctk_checkbox.py +++ b/customtkinter/windows/widgets/ctk_checkbox.py @@ -2,11 +2,11 @@ import tkinter import sys from typing import Union, Tuple, Callable, Optional -from .core_rendering.ctk_canvas import CTkCanvas -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass -from .font.ctk_font import CTkFont +from .core_rendering import CTkCanvas +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass +from .font import CTkFont class CTkCheckBox(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_combobox.py b/customtkinter/windows/widgets/ctk_combobox.py index 0e91830..070919a 100644 --- a/customtkinter/windows/widgets/ctk_combobox.py +++ b/customtkinter/windows/widgets/ctk_combobox.py @@ -2,12 +2,12 @@ import tkinter import sys from typing import Union, Tuple, Callable, List, Optional -from .core_widget_classes.dropdown_menu import DropdownMenu -from .core_rendering.ctk_canvas import CTkCanvas -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass -from .font.ctk_font import CTkFont +from .core_widget_classes import DropdownMenu +from .core_rendering import CTkCanvas +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass +from .font import CTkFont class CTkComboBox(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_entry.py b/customtkinter/windows/widgets/ctk_entry.py index 9b4551a..ac1edb6 100644 --- a/customtkinter/windows/widgets/ctk_entry.py +++ b/customtkinter/windows/widgets/ctk_entry.py @@ -1,13 +1,12 @@ import tkinter from typing import Union, Tuple, Optional -from .core_rendering.ctk_canvas import CTkCanvas -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass -from .font.ctk_font import CTkFont - -from customtkinter.utility.utility_functions import pop_from_dict_by_set, check_kwargs_empty +from .core_rendering import CTkCanvas +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass +from .font import CTkFont +from .utility import pop_from_dict_by_set, check_kwargs_empty class CTkEntry(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_frame.py b/customtkinter/windows/widgets/ctk_frame.py index abc71e4..baa9fc3 100644 --- a/customtkinter/windows/widgets/ctk_frame.py +++ b/customtkinter/windows/widgets/ctk_frame.py @@ -1,9 +1,9 @@ from typing import Union, Tuple, List, Optional -from .core_rendering.ctk_canvas import CTkCanvas -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass +from .core_rendering import CTkCanvas +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass class CTkFrame(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_label.py b/customtkinter/windows/widgets/ctk_label.py index e734beb..cd1f661 100644 --- a/customtkinter/windows/widgets/ctk_label.py +++ b/customtkinter/windows/widgets/ctk_label.py @@ -1,14 +1,13 @@ import tkinter from typing import Union, Tuple, Callable, Optional -from .core_rendering.ctk_canvas import CTkCanvas -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass -from .font.ctk_font import CTkFont -from .image.ctk_image import CTkImage - -from customtkinter.utility.utility_functions import pop_from_dict_by_set, check_kwargs_empty +from .core_rendering import CTkCanvas +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass +from .font import CTkFont +from .image import CTkImage +from .utility import pop_from_dict_by_set, check_kwargs_empty class CTkLabel(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_optionmenu.py b/customtkinter/windows/widgets/ctk_optionmenu.py index a9fde91..e6229fe 100644 --- a/customtkinter/windows/widgets/ctk_optionmenu.py +++ b/customtkinter/windows/widgets/ctk_optionmenu.py @@ -2,12 +2,12 @@ import tkinter import sys from typing import Union, Tuple, Callable, Optional -from .core_rendering.ctk_canvas import CTkCanvas -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass -from .core_widget_classes.dropdown_menu import DropdownMenu -from .font.ctk_font import CTkFont +from .core_rendering import CTkCanvas +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass +from .core_widget_classes import DropdownMenu +from .font import CTkFont class CTkOptionMenu(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_progressbar.py b/customtkinter/windows/widgets/ctk_progressbar.py index 1fcc396..2859ff4 100644 --- a/customtkinter/windows/widgets/ctk_progressbar.py +++ b/customtkinter/windows/widgets/ctk_progressbar.py @@ -2,10 +2,10 @@ import tkinter import math from typing import Union, Tuple, Optional -from .core_rendering.ctk_canvas import CTkCanvas -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass +from .core_rendering import CTkCanvas +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass class CTkProgressBar(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_radiobutton.py b/customtkinter/windows/widgets/ctk_radiobutton.py index 31c95a0..9ba3a29 100644 --- a/customtkinter/windows/widgets/ctk_radiobutton.py +++ b/customtkinter/windows/widgets/ctk_radiobutton.py @@ -2,11 +2,11 @@ import tkinter import sys from typing import Union, Tuple, Callable, Optional -from .core_rendering.ctk_canvas import CTkCanvas -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass -from .font.ctk_font import CTkFont +from .core_rendering import CTkCanvas +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass +from .font import CTkFont class CTkRadioButton(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_scrollbar.py b/customtkinter/windows/widgets/ctk_scrollbar.py index 59e5dc7..99134ff 100644 --- a/customtkinter/windows/widgets/ctk_scrollbar.py +++ b/customtkinter/windows/widgets/ctk_scrollbar.py @@ -1,10 +1,10 @@ import sys from typing import Union, Tuple, Callable, Optional -from .core_rendering.ctk_canvas import CTkCanvas -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass +from .core_rendering import CTkCanvas +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass class CTkScrollbar(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_segmented_button.py b/customtkinter/windows/widgets/ctk_segmented_button.py index 68c6369..05b57c9 100644 --- a/customtkinter/windows/widgets/ctk_segmented_button.py +++ b/customtkinter/windows/widgets/ctk_segmented_button.py @@ -1,10 +1,10 @@ import tkinter from typing import Union, Tuple, List, Dict, Callable, Optional, Literal -from .theme.theme_manager import ThemeManager +from .theme import ThemeManager +from .font import CTkFont from .ctk_button import CTkButton from .ctk_frame import CTkFrame -from .font.ctk_font import CTkFont class CTkSegmentedButton(CTkFrame): diff --git a/customtkinter/windows/widgets/ctk_slider.py b/customtkinter/windows/widgets/ctk_slider.py index 4b48507..a88e956 100644 --- a/customtkinter/windows/widgets/ctk_slider.py +++ b/customtkinter/windows/widgets/ctk_slider.py @@ -2,10 +2,10 @@ import tkinter import sys from typing import Union, Tuple, Callable, Optional -from .core_rendering.ctk_canvas import CTkCanvas -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass +from .core_rendering import CTkCanvas +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass class CTkSlider(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_switch.py b/customtkinter/windows/widgets/ctk_switch.py index e315c93..a986a65 100644 --- a/customtkinter/windows/widgets/ctk_switch.py +++ b/customtkinter/windows/widgets/ctk_switch.py @@ -2,11 +2,11 @@ import tkinter import sys from typing import Union, Tuple, Callable, Optional -from .core_rendering.ctk_canvas import CTkCanvas -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass -from .font.ctk_font import CTkFont +from .core_rendering import CTkCanvas +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass +from .font import CTkFont class CTkSwitch(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_tabview.py b/customtkinter/windows/widgets/ctk_tabview.py index 543205c..75bde4b 100644 --- a/customtkinter/windows/widgets/ctk_tabview.py +++ b/customtkinter/windows/widgets/ctk_tabview.py @@ -1,12 +1,12 @@ import tkinter from typing import Union, Tuple, Dict, List, Callable, Optional -from .theme.theme_manager import ThemeManager +from .theme import ThemeManager from .ctk_frame import CTkFrame -from .core_widget_classes.widget_base_class import CTkBaseClass +from .core_rendering import CTkCanvas +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass from .ctk_segmented_button import CTkSegmentedButton -from .core_rendering.ctk_canvas import CTkCanvas -from .core_rendering.draw_engine import DrawEngine class CTkTabview(CTkBaseClass): diff --git a/customtkinter/windows/widgets/ctk_textbox.py b/customtkinter/windows/widgets/ctk_textbox.py index 991a178..2ba985a 100644 --- a/customtkinter/windows/widgets/ctk_textbox.py +++ b/customtkinter/windows/widgets/ctk_textbox.py @@ -1,14 +1,13 @@ import tkinter from typing import Union, Tuple, Optional -from .core_rendering.ctk_canvas import CTkCanvas +from .core_rendering import CTkCanvas from .ctk_scrollbar import CTkScrollbar -from .theme.theme_manager import ThemeManager -from .core_rendering.draw_engine import DrawEngine -from .core_widget_classes.widget_base_class import CTkBaseClass -from .font.ctk_font import CTkFont - -from customtkinter.utility.utility_functions import pop_from_dict_by_set, check_kwargs_empty +from .theme import ThemeManager +from .core_rendering import DrawEngine +from .core_widget_classes import CTkBaseClass +from .font import CTkFont +from .utility import pop_from_dict_by_set, check_kwargs_empty class CTkTextbox(CTkBaseClass): diff --git a/customtkinter/windows/widgets/font/__init__.py b/customtkinter/windows/widgets/font/__init__.py index e69de29..9c3d6ff 100644 --- a/customtkinter/windows/widgets/font/__init__.py +++ b/customtkinter/windows/widgets/font/__init__.py @@ -0,0 +1,24 @@ +import os +import sys + +from .ctk_font import CTkFont +from .font_manager import FontManager + +# import DrawEngine to set preferred_drawing_method if loading shapes font fails +from ..core_rendering import DrawEngine + +FontManager.init_font_manager() + +# 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")) +FontManager.load_font(os.path.join(script_directory, "assets", "fonts", "Roboto", "Roboto-Medium.ttf")) + +# load font necessary for rendering the widgets (used on Windows/Linux) +if FontManager.load_font(os.path.join(script_directory, "assets", "fonts", "CustomTkinter_shapes_font.otf")) is False: + # change draw method if font loading failed + if DrawEngine.preferred_drawing_method == "font_shapes": + sys.stderr.write("customtkinter.__init__ warning: " + + "Preferred drawing method 'font_shapes' can not be used because the font file could not be loaded.\n" + + "Using 'circle_shapes' instead. The rendering quality will be bad!\n") + DrawEngine.preferred_drawing_method = "circle_shapes" diff --git a/customtkinter/windows/widgets/font/ctk_font.py b/customtkinter/windows/widgets/font/ctk_font.py index 64c6af0..69fb3f7 100644 --- a/customtkinter/windows/widgets/font/ctk_font.py +++ b/customtkinter/windows/widgets/font/ctk_font.py @@ -2,7 +2,7 @@ from tkinter.font import Font import copy from typing import List, Callable, Tuple, Optional, Literal -from ..theme.theme_manager import ThemeManager +from ..theme import ThemeManager class CTkFont(Font): diff --git a/customtkinter/windows/widgets/image/__init__.py b/customtkinter/windows/widgets/image/__init__.py index e69de29..b712c89 100644 --- a/customtkinter/windows/widgets/image/__init__.py +++ b/customtkinter/windows/widgets/image/__init__.py @@ -0,0 +1 @@ +from .ctk_image import CTkImage diff --git a/customtkinter/windows/widgets/scaling/__init__.py b/customtkinter/windows/widgets/scaling/__init__.py index e69de29..8fc0db8 100644 --- a/customtkinter/windows/widgets/scaling/__init__.py +++ b/customtkinter/windows/widgets/scaling/__init__.py @@ -0,0 +1,7 @@ +import sys + +from .scaling_base_class import CTkScalingBaseClass +from .scaling_tracker import ScalingTracker + +if sys.platform.startswith("win") and sys.getwindowsversion().build < 9000: # No automatic scaling on Windows < 8.1 + ScalingTracker.deactivate_automatic_dpi_awareness = True diff --git a/customtkinter/windows/widgets/scaling/scaling_base_class.py b/customtkinter/windows/widgets/scaling/scaling_base_class.py index 4b080c7..74838bc 100644 --- a/customtkinter/windows/widgets/scaling/scaling_base_class.py +++ b/customtkinter/windows/widgets/scaling/scaling_base_class.py @@ -7,7 +7,7 @@ except ImportError: from typing_extensions import Literal from .scaling_tracker import ScalingTracker -from ..font.ctk_font import CTkFont +from ..font import CTkFont class CTkScalingBaseClass: diff --git a/customtkinter/windows/widgets/theme/__init__.py b/customtkinter/windows/widgets/theme/__init__.py index e69de29..bd7395a 100644 --- a/customtkinter/windows/widgets/theme/__init__.py +++ b/customtkinter/windows/widgets/theme/__init__.py @@ -0,0 +1,9 @@ +from .theme_manager import ThemeManager + +# load default blue theme +try: + ThemeManager.load_theme("blue") +except FileNotFoundError as err: + raise FileNotFoundError(f"{err}\n\nThe .json theme file for CustomTkinter could not be found.\n" + + f"If packaging with pyinstaller was used, have a look at the wiki:\n" + + f"https://github.com/TomSchimansky/CustomTkinter/wiki/Packaging#windows-pyinstaller-auto-py-to-exe") diff --git a/customtkinter/windows/widgets/utility/__init__.py b/customtkinter/windows/widgets/utility/__init__.py new file mode 100644 index 0000000..c4b6fe8 --- /dev/null +++ b/customtkinter/windows/widgets/utility/__init__.py @@ -0,0 +1 @@ +from .utility_functions import pop_from_dict_by_set, check_kwargs_empty diff --git a/customtkinter/utility/utility_functions.py b/customtkinter/windows/widgets/utility/utility_functions.py similarity index 99% rename from customtkinter/utility/utility_functions.py rename to customtkinter/windows/widgets/utility/utility_functions.py index 8ae6475..8cb1352 100644 --- a/customtkinter/utility/utility_functions.py +++ b/customtkinter/windows/widgets/utility/utility_functions.py @@ -1,5 +1,4 @@ - def pop_from_dict_by_set(dictionary: dict, valid_keys: set): """ remove and create new dict with key value pairs of dictionary, where key is in valid_keys """ new_dictionary = {} diff --git a/examples/complex_example.py b/examples/complex_example.py index 925d4a2..978a706 100644 --- a/examples/complex_example.py +++ b/examples/complex_example.py @@ -7,7 +7,6 @@ customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "gre class App(customtkinter.CTk): - def __init__(self): super().__init__() @@ -26,21 +25,21 @@ class App(customtkinter.CTk): self.sidebar_frame.grid_rowconfigure(4, weight=1) self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="CustomTkinter", font=customtkinter.CTkFont(size=20, weight="bold")) self.logo_label.grid(row=0, column=0, padx=20, pady=(20, 10)) - self.sidebar_button_1 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_callback) + self.sidebar_button_1 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_event) self.sidebar_button_1.grid(row=1, column=0, padx=20, pady=10) - self.sidebar_button_2 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_callback) + self.sidebar_button_2 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_event) self.sidebar_button_2.grid(row=2, column=0, padx=20, pady=10) - self.sidebar_button_3 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_callback) + self.sidebar_button_3 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_event) self.sidebar_button_3.grid(row=3, column=0, padx=20, pady=10) self.appearance_mode_label = customtkinter.CTkLabel(self.sidebar_frame, text="Appearance Mode:", anchor="w") self.appearance_mode_label.grid(row=5, column=0, padx=20, pady=(10, 0)) self.appearance_mode_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["Light", "Dark", "System"], - command=self.change_appearance_mode) + command=self.change_appearance_mode_event) self.appearance_mode_optionemenu.grid(row=6, column=0, padx=20, pady=(10, 10)) self.scaling_label = customtkinter.CTkLabel(self.sidebar_frame, text="UI Scaling:", anchor="w") self.scaling_label.grid(row=7, column=0, padx=20, pady=(10, 0)) self.scaling_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["80%", "90%", "100%", "110%", "120%"], - command=self.change_scaling) + command=self.change_scaling_event) self.scaling_optionemenu.grid(row=8, column=0, padx=20, pady=(10, 20)) # create main entry and button @@ -70,7 +69,7 @@ class App(customtkinter.CTk): values=["Value 1", "Value 2", "Value Long....."]) self.combobox_1.grid(row=1, column=0, padx=20, pady=(10, 10)) self.string_input_button = customtkinter.CTkButton(self.tabview.tab("CTkTabview"), text="Open CTkInputDialog", - command=self.open_input_dialog) + command=self.open_input_dialog_event) self.string_input_button.grid(row=2, column=0, padx=20, pady=(10, 10)) self.label_tab_2 = customtkinter.CTkLabel(self.tabview.tab("Tab 2"), text="CTkLabel on Tab 2") self.label_tab_2.grid(row=0, column=0, padx=20, pady=20) @@ -137,18 +136,18 @@ class App(customtkinter.CTk): self.seg_button_1.configure(values=["CTkSegmentedButton", "Value 2", "Value 3"]) self.seg_button_1.set("Value 2") - def open_input_dialog(self): + def open_input_dialog_event(self): dialog = customtkinter.CTkInputDialog(text="Type in a number:", title="CTkInputDialog") print("CTkInputDialog:", dialog.get_input()) - def change_appearance_mode(self, new_appearance_mode: str): + def change_appearance_mode_event(self, new_appearance_mode: str): customtkinter.set_appearance_mode(new_appearance_mode) - def change_scaling(self, new_scaling: str): + def change_scaling_event(self, new_scaling: str): new_scaling_float = int(new_scaling.replace("%", "")) / 100 customtkinter.set_widget_scaling(new_scaling_float) - def sidebar_button_callback(self): + def sidebar_button_event(self): print("sidebar_button click") diff --git a/test/unit_tests/test_ctk.py b/test/unit_tests/test_ctk.py index 5920909..bb95d29 100644 --- a/test/unit_tests/test_ctk.py +++ b/test/unit_tests/test_ctk.py @@ -62,15 +62,15 @@ class TestCTk(): customtkinter.ScalingTracker.set_window_scaling(1.5) self.root_ctk.geometry("300x400") - assert self.root_ctk.current_width == 300 and self.root_ctk.current_height == 400 + assert self.root_ctk._current_width == 300 and self.root_ctk._current_height == 400 assert self.root_ctk.window_scaling == 1.5 * customtkinter.ScalingTracker.get_window_dpi_scaling(self.root_ctk) self.root_ctk.maxsize(400, 500) self.root_ctk.geometry("500x500") - assert self.root_ctk.current_width == 400 and self.root_ctk.current_height == 500 + assert self.root_ctk._current_width == 400 and self.root_ctk._current_height == 500 customtkinter.ScalingTracker.set_window_scaling(1) - assert self.root_ctk.current_width == 400 and self.root_ctk.current_height == 500 + assert self.root_ctk._current_width == 400 and self.root_ctk._current_height == 500 print("successful") def test_configure(self):