From 063c1f8b6a93c43c742aa81f28750b23e3168416 Mon Sep 17 00:00:00 2001 From: Tom Schimansky Date: Fri, 31 Dec 2021 19:07:53 +0100 Subject: [PATCH] added CTk class which overrides tkinter.Tk for automatic background color changes --- customtkinter/__init__.py | 3 +- customtkinter/customtkinter_color_manager.py | 1 + customtkinter/customtkinter_tk.py | 70 ++++++++++++++++++++ examples/complex_example.py | 13 +--- examples/complex_example_other_style.py | 13 +--- examples/enable_disable_button_example.py | 4 +- examples/example_background_image.py | 7 +- examples/simple_example.py | 5 +- examples/simple_example_images.py | 6 +- setup.py | 2 +- 10 files changed, 84 insertions(+), 40 deletions(-) create mode 100644 customtkinter/customtkinter_tk.py diff --git a/customtkinter/__init__.py b/customtkinter/__init__.py index fef298f..83afb93 100644 --- a/customtkinter/__init__.py +++ b/customtkinter/__init__.py @@ -1,4 +1,4 @@ -__version__ = "1.4" +__version__ = "1.5" from .customtkinter_button import CTkButton from .customtkinter_slider import CTkSlider @@ -8,6 +8,7 @@ from .customtkinter_label import CTkLabel from .customtkinter_entry import CTkEntry from .customtkinter_dialog import CTkDialog from .customtkinter_checkbox import CTkCheckBox +from .customtkinter_tk import CTk from .appearance_mode_tracker import AppearanceModeTracker, SystemAppearanceModeListenerNoThread from .customtkinter_color_manager import CTkColorManager diff --git a/customtkinter/customtkinter_color_manager.py b/customtkinter/customtkinter_color_manager.py index 2db8d90..73f6ab1 100644 --- a/customtkinter/customtkinter_color_manager.py +++ b/customtkinter/customtkinter_color_manager.py @@ -3,6 +3,7 @@ import sys class CTkColorManager: + WINDOW_BG = ("#ECECEC", "#323232") # macOS standard light and dark window bg colors MAIN = ("#1C94CF", "#1C94CF") MAIN_HOVER = ("#5FB4DD", "#5FB4DD") ENTRY = ("white", "#222222") diff --git a/customtkinter/customtkinter_tk.py b/customtkinter/customtkinter_tk.py new file mode 100644 index 0000000..7112e4f --- /dev/null +++ b/customtkinter/customtkinter_tk.py @@ -0,0 +1,70 @@ +import tkinter +from distutils.version import StrictVersion as Version +import sys +import os +import platform + +from .appearance_mode_tracker import AppearanceModeTracker +from .customtkinter_color_manager import CTkColorManager + + +class CTk(tkinter.Tk): + def __init__(self, *args, + bg_color=CTkColorManager.WINDOW_BG, + **kwargs): + + self.enable_macos_dark_title_bar() + self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark" + + self.bg_color = bg_color + if "bg" in kwargs: + self.bg_color = kwargs["bg"] + del kwargs["bg"] + elif "background" in kwargs: + self.bg_color = kwargs["background"] + del kwargs["background"] + + super().__init__(*args, **kwargs) + + AppearanceModeTracker.add(self.set_appearance_mode) + super().configure(bg=CTkColorManager.single_color(self.bg_color, self.appearance_mode)) + + def destroy(self): + self.disable_macos_dark_title_bar() + super().destroy() + + def config(self, *args, **kwargs): + self.configure(*args, **kwargs) + + def configure(self, *args, **kwargs): + if "bg" in kwargs: + self.bg_color = kwargs["bg"] + elif "background" in kwargs: + self.bg_color = kwargs["background"] + + super().configure(*args, **kwargs) + + @staticmethod + def enable_macos_dark_title_bar(): + if sys.platform == "darwin": # macOS + if Version(platform.python_version()) < Version("3.10"): + if Version(tkinter.Tcl().call("info", "patchlevel")) >= Version("8.6.9"): # Tcl/Tk >= 8.6.9 + os.system("defaults write -g NSRequiresAquaSystemAppearance -bool No") + + @staticmethod + def disable_macos_dark_title_bar(): + if sys.platform == "darwin": # macOS + if Version(platform.python_version()) < Version("3.10"): + if Version(tkinter.Tcl().call("info", "patchlevel")) >= Version("8.6.9"): # Tcl/Tk >= 8.6.9 + os.system("defaults delete -g NSRequiresAquaSystemAppearance") + # This command reverts the dark-mode setting for all programs. + + def set_appearance_mode(self, mode_string): + if mode_string.lower() == "dark": + self.appearance_mode = 1 + elif mode_string.lower() == "light": + self.appearance_mode = 0 + + print("set",self.bg_color) + + super().configure(bg=CTkColorManager.single_color(self.bg_color, self.appearance_mode)) diff --git a/examples/complex_example.py b/examples/complex_example.py index f92da98..a947fd7 100644 --- a/examples/complex_example.py +++ b/examples/complex_example.py @@ -6,22 +6,14 @@ import sys customtkinter.set_appearance_mode("System") # Other: "Light", "Dark" -class App(tkinter.Tk): +class App(customtkinter.CTk): APP_NAME = "CustomTkinter complex example" WIDTH = 700 HEIGHT = 500 def __init__(self, *args, **kwargs): - customtkinter.enable_macos_darkmode() - - tkinter.Tk.__init__(self, *args, **kwargs) - - # color the background of the Tk window if mode is not System - if customtkinter.get_appearance_mode() == "Dark": - self.configure(bg="#323232") # set window background to dark color - elif customtkinter.get_appearance_mode() == "Light": - self.configure(bg="#ECECEC") # set window background to dark color + super().__init__(*args, **kwargs) self.title(App.APP_NAME) self.geometry(str(App.WIDTH) + "x" + str(App.HEIGHT)) @@ -164,7 +156,6 @@ class App(tkinter.Tk): print("Button pressed") def on_closing(self, event=0): - customtkinter.disable_macos_darkmode() self.destroy() def start(self): diff --git a/examples/complex_example_other_style.py b/examples/complex_example_other_style.py index 505d9d0..faadca3 100644 --- a/examples/complex_example_other_style.py +++ b/examples/complex_example_other_style.py @@ -7,7 +7,7 @@ import sys customtkinter.set_appearance_mode("Dark") # Other: "Light", "System" -class App(tkinter.Tk): +class App(customtkinter.CTk): APP_NAME = "CustomTkinter complex example" WIDTH = 700 @@ -18,15 +18,7 @@ class App(tkinter.Tk): MAIN_HOVER = "#458577" def __init__(self, *args, **kwargs): - customtkinter.enable_macos_darkmode() - - tkinter.Tk.__init__(self, *args, **kwargs) - - # color the background of the Tk window if mode is not System - if customtkinter.get_appearance_mode() == "Dark": - self.configure(bg="#323232") # set window background to dark color - elif customtkinter.get_appearance_mode() == "Light": - self.configure(bg="#ECECEC") # set window background to dark color + super().__init__(self, *args, **kwargs) self.title(App.APP_NAME) self.geometry(str(App.WIDTH) + "x" + str(App.HEIGHT)) @@ -178,7 +170,6 @@ class App(tkinter.Tk): print("Button pressed") def on_closing(self, event=0): - customtkinter.disable_macos_darkmode() self.destroy() def start(self): diff --git a/examples/enable_disable_button_example.py b/examples/enable_disable_button_example.py index 2aeca82..cf45c62 100644 --- a/examples/enable_disable_button_example.py +++ b/examples/enable_disable_button_example.py @@ -1,10 +1,9 @@ import tkinter import customtkinter # <- import the CustomTkinter module -customtkinter.enable_macos_darkmode() customtkinter.set_appearance_mode("System") # Other: "Dark", "Light" -root_tk = tkinter.Tk() # create the Tk window like you normally do +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("400x240") root_tk.title("CustomTkinter Test") @@ -32,4 +31,3 @@ button_2 = customtkinter.CTkButton(master=frame_1, text="Button_2", button_2.place(relx=0.5, rely=0.7, anchor=tkinter.CENTER) root_tk.mainloop() -customtkinter.disable_macos_darkmode() diff --git a/examples/example_background_image.py b/examples/example_background_image.py index 7b58131..e1ca2ac 100644 --- a/examples/example_background_image.py +++ b/examples/example_background_image.py @@ -9,16 +9,14 @@ customtkinter.set_appearance_mode("Dark") # Other: "Light", "System" PATH = os.path.dirname(os.path.realpath(__file__)) -class App(tkinter.Tk): +class App(customtkinter.CTk): APP_NAME = "CustomTkinter background gardient" WIDTH = 900 HEIGHT = 600 def __init__(self, *args, **kwargs): - customtkinter.enable_macos_darkmode() - - tkinter.Tk.__init__(self, *args, **kwargs) + super().__init__(self, *args, **kwargs) self.title(App.APP_NAME) self.geometry(str(App.WIDTH) + "x" + str(App.HEIGHT)) @@ -54,7 +52,6 @@ class App(tkinter.Tk): print("Button pressed") def on_closing(self, event=0): - customtkinter.disable_macos_darkmode() self.destroy() def start(self): diff --git a/examples/simple_example.py b/examples/simple_example.py index 7510ca5..a43c026 100644 --- a/examples/simple_example.py +++ b/examples/simple_example.py @@ -1,9 +1,7 @@ import tkinter import customtkinter # <- import the CustomTkinter module -customtkinter.enable_macos_darkmode() - -root_tk = tkinter.Tk() # create the Tk window like you normally do +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("400x300") root_tk.title("CustomTkinter Test") @@ -46,4 +44,3 @@ checkbox_1 = customtkinter.CTkCheckBox(master=frame_1, command=check_box_functio checkbox_1.place(relx=0.5, rely=0.9, anchor=tkinter.CENTER) root_tk.mainloop() -customtkinter.disable_macos_darkmode() diff --git a/examples/simple_example_images.py b/examples/simple_example_images.py index 1407be0..f9c52fa 100644 --- a/examples/simple_example_images.py +++ b/examples/simple_example_images.py @@ -5,10 +5,9 @@ import os PATH = os.path.dirname(os.path.realpath(__file__)) -customtkinter.enable_macos_darkmode() customtkinter.set_appearance_mode("System") # Other: "Dark", "Light" -root_tk = tkinter.Tk() # create the Tk window like you normally do +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("400x400") root_tk.title("CustomTkinter Test") @@ -46,5 +45,4 @@ button_4.place(relx=0.5, rely=0.85, relwidth=0.5, anchor=tkinter.CENTER) button_4.configure(text=None) -root_tk.mainloop() -customtkinter.disable_macos_darkmode() +root_tk.mainloop() \ No newline at end of file diff --git a/setup.py b/setup.py index 44f9c12..9e46160 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ def read(filename): setup(name="customtkinter", - version="1.4", + version="1.5", author="Tom Schimansky", license="Creative Commons Zero v1.0 Universal", url="https://github.com/TomSchimansky/CustomTkinter",