diff --git a/customtkinter/__init__.py b/customtkinter/__init__.py index 9d49d5f..e6ea883 100644 --- a/customtkinter/__init__.py +++ b/customtkinter/__init__.py @@ -1,4 +1,4 @@ -__version__ = "2.0" +__version__ = "2.1" from .customtkinter_button import CTkButton from .customtkinter_slider import CTkSlider diff --git a/customtkinter/customtkinter_color_manager.py b/customtkinter/customtkinter_color_manager.py index f92fb61..5d66e13 100644 --- a/customtkinter/customtkinter_color_manager.py +++ b/customtkinter/customtkinter_color_manager.py @@ -8,6 +8,7 @@ class CTkColorManager: MAIN_HOVER = None ENTRY = None TEXT = None + PLACEHOLDER_TEXT = None LABEL_BG = None SLIDER_BG = None SLIDER_PROGRESS = None @@ -26,6 +27,7 @@ class CTkColorManager: cls.MAIN_HOVER = ("#5FB4DD", "#5FB4DD") cls.ENTRY = ("white", "#222222") cls.TEXT = ("black", "white") + cls.PLACEHOLDER_TEXT = ("gray52", "gray62") cls.LABEL_BG = ("white", "#626061") cls.SLIDER_BG = ("#6B6B6B", "#222222") cls.SLIDER_PROGRESS = ("#A5A6A5", "#555555") diff --git a/customtkinter/customtkinter_entry.py b/customtkinter/customtkinter_entry.py index 7584082..903e214 100644 --- a/customtkinter/customtkinter_entry.py +++ b/customtkinter/customtkinter_entry.py @@ -13,7 +13,9 @@ class CTkEntry(tkinter.Frame): bg_color=None, fg_color="CTkColorManager", text_color="CTkColorManager", + placeholder_text_color="CTkColorManager", text_font=None, + placeholder_text=None, corner_radius=8, width=120, height=30, @@ -52,6 +54,7 @@ class CTkEntry(tkinter.Frame): self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color self.fg_color = CTkColorManager.ENTRY if fg_color == "CTkColorManager" else fg_color self.text_color = CTkColorManager.TEXT if text_color == "CTkColorManager" else text_color + self.placeholder_text_color = CTkColorManager.PLACEHOLDER_TEXT if placeholder_text_color == "CTkColorManager" else placeholder_text_color if text_font is None: if sys.platform == "darwin": # macOS @@ -63,9 +66,12 @@ class CTkEntry(tkinter.Frame): else: self.text_font = text_font + self.placeholder_text = placeholder_text + self.placeholder_text_active = False + self.pre_placeholder_arguments = {} # some set arguments of the entry will be changed for placeholder and then set back + self.width = width self.height = height - self.corner_radius = self.calc_optimal_corner_radius(corner_radius) # optimise for less artifacts if self.corner_radius*2 > self.height: @@ -91,8 +97,12 @@ class CTkEntry(tkinter.Frame): self.fg_parts = [] - self.bind('', self.update_dimensions) + super().bind('', self.update_dimensions) + self.entry.bind('', self.set_placeholder) + self.entry.bind('', self.clear_placeholder) + self.draw() + self.set_placeholder() def destroy(self): AppearanceModeTracker.remove(self.change_appearance_mode) @@ -132,6 +142,23 @@ class CTkEntry(tkinter.Frame): self.draw() + def set_placeholder(self, event=None): + if self.placeholder_text is not None: + if not self.placeholder_text_active and self.entry.get() == "": + self.placeholder_text_active = True + self.pre_placeholder_arguments = {"show": self.entry.cget("show")} + self.entry.config(fg=CTkColorManager.single_color(self.placeholder_text_color, self.appearance_mode), show="") + self.entry.delete(0, tkinter.END) + self.entry.insert(0, self.placeholder_text) + + def clear_placeholder(self, event=None): + if self.placeholder_text_active: + self.placeholder_text_active = False + self.entry.config(fg=CTkColorManager.single_color(self.text_color, self.appearance_mode)) + self.entry.delete(0, tkinter.END) + for argument, value in self.pre_placeholder_arguments.items(): + self.entry[argument] = value + def draw(self): self.canvas.delete("all") self.fg_parts = [] @@ -189,6 +216,9 @@ class CTkEntry(tkinter.Frame): self.entry.configure(fg=self.text_color, insertbackground=self.text_color) + def bind(self, *args, **kwargs): + self.entry.bind(*args, **kwargs) + def config(self, *args, **kwargs): self.configure(*args, **kwargs) @@ -228,13 +258,19 @@ class CTkEntry(tkinter.Frame): self.draw() def delete(self, *args, **kwargs): - return self.entry.delete(*args, **kwargs) + self.entry.delete(*args, **kwargs) + self.set_placeholder() + return def insert(self, *args, **kwargs): + self.clear_placeholder() return self.entry.insert(*args, **kwargs) def get(self): - return self.entry.get() + if self.placeholder_text_active: + return "" + else: + return self.entry.get() def change_appearance_mode(self, mode_string): if mode_string.lower() == "dark": diff --git a/examples/example_background_image.py b/examples/example_background_image.py index c73ba58..4a51b09 100644 --- a/examples/example_background_image.py +++ b/examples/example_background_image.py @@ -46,13 +46,11 @@ class App(customtkinter.CTk): fg_color=("gray70", "gray20"), text="CustomTkinter\ninterface example") self.label_1.place(relx=0.5, rely=0.3, anchor=tkinter.CENTER) - self.entry_1 = customtkinter.CTkEntry(master=self.frame, corner_radius=20, width=200) + self.entry_1 = customtkinter.CTkEntry(master=self.frame, corner_radius=20, width=200, placeholder_text="username") self.entry_1.place(relx=0.5, rely=0.52, anchor=tkinter.CENTER) - self.entry_1.insert(0, "username") - self.entry_2 = customtkinter.CTkEntry(master=self.frame, corner_radius=20, width=200, show="*") + self.entry_2 = customtkinter.CTkEntry(master=self.frame, corner_radius=20, width=200, show="*", placeholder_text="password") self.entry_2.place(relx=0.5, rely=0.6, anchor=tkinter.CENTER) - self.entry_2.insert(0, "password") self.button_2 = customtkinter.CTkButton(master=self.frame, text="Login", corner_radius=6, command=self.button_event, width=200) diff --git a/examples/simple_example.py b/examples/simple_example.py index 701d6e7..e6b895c 100644 --- a/examples/simple_example.py +++ b/examples/simple_example.py @@ -10,7 +10,7 @@ root_tk.title("CustomTkinter Test") def button_function(): - print("Button click") + print("Button click", label_1.text_label.cget("text")) def slider_function(value): @@ -40,7 +40,7 @@ slider_1 = customtkinter.CTkSlider(master=frame_1, command=slider_function, from slider_1.pack(pady=y_padding, padx=10) slider_1.set(0.5) -entry_1 = customtkinter.CTkEntry(master=frame_1) +entry_1 = customtkinter.CTkEntry(master=frame_1, placeholder_text="CTkEntry") entry_1.pack(pady=y_padding, padx=10) checkbox_1 = customtkinter.CTkCheckBox(master=frame_1, command=check_box_function) diff --git a/setup.py b/setup.py index 6f5c40c..61a088a 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ def read(filename): setup(name="customtkinter", - version="2.0", + version="2.1", author="Tom Schimansky", license="Creative Commons Zero v1.0 Universal", url="https://github.com/TomSchimansky/CustomTkinter",