From 88155e5b013ce0bb404b890849c16b66c34246ab Mon Sep 17 00:00:00 2001 From: misygauziya Date: Thu, 13 Jul 2023 11:01:25 +0900 Subject: [PATCH 01/10] =?UTF-8?q?=E8=B5=B7=E5=8B=95=E6=99=82=E3=81=ABTople?= =?UTF-8?q?velWindowConfig=E3=82=92=E7=94=9F=E6=88=90=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VRCT.py | 14 +++++++++----- window_config.py | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/VRCT.py b/VRCT.py index 9915b82c..c46216d3 100644 --- a/VRCT.py +++ b/VRCT.py @@ -397,12 +397,16 @@ class App(CTk): # delete window self.protocol("WM_DELETE_WINDOW", self.delete_window) + self.config_window = ToplevelWindowConfig(self) + self.config_window.withdraw() + def button_config_callback(self): - if self.config_window is None or not self.config_window.winfo_exists(): - self.config_window = ToplevelWindowConfig(self) - self.checkbox_translation.configure(state="disabled") - self.checkbox_transcription_send.configure(state="disabled") - self.checkbox_transcription_receive.configure(state="disabled") + # if self.config_window is None or not self.config_window.winfo_exists(): + # # self.config_window = ToplevelWindowConfig(self) + self.config_window.deiconify() + self.checkbox_translation.configure(state="disabled") + self.checkbox_transcription_send.configure(state="disabled") + self.checkbox_transcription_receive.configure(state="disabled") self.config_window.focus() def button_information_callback(self): diff --git a/window_config.py b/window_config.py index 481acea6..27ab3859 100644 --- a/window_config.py +++ b/window_config.py @@ -406,7 +406,7 @@ class ToplevelWindowConfig(CTkToplevel): self.parent.checkbox_translation.configure(state="normal") self.parent.checkbox_transcription_send.configure(state="normal") self.parent.checkbox_transcription_receive.configure(state="normal") - self.parent.config_window.destroy() + self.parent.config_window.withdraw() def entry_message_format_callback(self, event): value = self.entry_message_format.get() From d11f9d716f402a8f45e1088d841e5cc86a60228f Mon Sep 17 00:00:00 2001 From: misygauziya Date: Thu, 13 Jul 2023 15:43:44 +0900 Subject: [PATCH 02/10] =?UTF-8?q?withdraw=E3=81=AE=E3=82=BF=E3=82=A4?= =?UTF-8?q?=E3=83=9F=E3=83=B3=E3=82=B0=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VRCT.py | 2 -- window_config.py | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/VRCT.py b/VRCT.py index c46216d3..66622465 100644 --- a/VRCT.py +++ b/VRCT.py @@ -398,11 +398,9 @@ class App(CTk): self.protocol("WM_DELETE_WINDOW", self.delete_window) self.config_window = ToplevelWindowConfig(self) - self.config_window.withdraw() def button_config_callback(self): # if self.config_window is None or not self.config_window.winfo_exists(): - # # self.config_window = ToplevelWindowConfig(self) self.config_window.deiconify() self.checkbox_translation.configure(state="disabled") self.checkbox_transcription_send.configure(state="disabled") diff --git a/window_config.py b/window_config.py index 27ab3859..1e4be837 100644 --- a/window_config.py +++ b/window_config.py @@ -16,6 +16,7 @@ class ToplevelWindowConfig(CTkToplevel): def __init__(self, parent, *args, **kwargs): super().__init__(parent, *args, **kwargs) + self.withdraw() self.parent = parent # self.geometry(f"{350}x{270}") # self.resizable(False, False) @@ -167,6 +168,7 @@ class ToplevelWindowConfig(CTkToplevel): save_json(self.parent.PATH_CONFIG, "FONT_FAMILY", self.parent.FONT_FAMILY) def optionmenu_ui_language_callback(self, choice): + self.withdraw() pre_language_yaml_data = get_localized_text(f"{self.parent.UI_LANGUAGE}") self.parent.UI_LANGUAGE = get_key_by_value(selectable_languages, choice) language_yaml_data = get_localized_text(f"{self.parent.UI_LANGUAGE}") @@ -186,6 +188,7 @@ class ToplevelWindowConfig(CTkToplevel): # self.parent.information_window.textbox_information.configure(font=customtkinter.CTkFont(family=choice)) # except: # pass + self.deiconify() def optionmenu_translation_translator_callback(self, choice): if self.parent.translator.authentication(choice, self.parent.AUTH_KEYS[choice]) is False: From 2cc9d6830370e229d45fb67c27a08226d34629f5 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Thu, 13 Jul 2023 15:52:30 +0900 Subject: [PATCH 03/10] remove comment out --- VRCT.py | 1 - 1 file changed, 1 deletion(-) diff --git a/VRCT.py b/VRCT.py index 66622465..00a2fc99 100644 --- a/VRCT.py +++ b/VRCT.py @@ -400,7 +400,6 @@ class App(CTk): self.config_window = ToplevelWindowConfig(self) def button_config_callback(self): - # if self.config_window is None or not self.config_window.winfo_exists(): self.config_window.deiconify() self.checkbox_translation.configure(state="disabled") self.checkbox_transcription_send.configure(state="disabled") From c7cc2ff55167abcd6e772aa2c5fd230a94046517 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Thu, 13 Jul 2023 15:53:32 +0900 Subject: [PATCH 04/10] test code CTkScrollableDropdown for font --- CTkScrollableDropdown/__init__.py | 12 + .../ctk_scrollable_dropdown.py | 321 ++++++++++++++++++ .../ctk_scrollable_dropdown_frame.py | 278 +++++++++++++++ window_config.py | 20 +- 4 files changed, 628 insertions(+), 3 deletions(-) create mode 100644 CTkScrollableDropdown/__init__.py create mode 100644 CTkScrollableDropdown/ctk_scrollable_dropdown.py create mode 100644 CTkScrollableDropdown/ctk_scrollable_dropdown_frame.py diff --git a/CTkScrollableDropdown/__init__.py b/CTkScrollableDropdown/__init__.py new file mode 100644 index 00000000..8ba844b7 --- /dev/null +++ b/CTkScrollableDropdown/__init__.py @@ -0,0 +1,12 @@ +""" +CustomTkinter Scrollable Dropdown Menu +Author: Akash Bora +License: MIT +This is a custom dropdown menu for customtkinter. +Homepage: https://github.com/Akascape/CTkScrollableDropdown +""" + +__version__ = '0.9' + +from .ctk_scrollable_dropdown import CTkScrollableDropdown +from .ctk_scrollable_dropdown_frame import CTkScrollableDropdownFrame diff --git a/CTkScrollableDropdown/ctk_scrollable_dropdown.py b/CTkScrollableDropdown/ctk_scrollable_dropdown.py new file mode 100644 index 00000000..c54b6197 --- /dev/null +++ b/CTkScrollableDropdown/ctk_scrollable_dropdown.py @@ -0,0 +1,321 @@ +''' +Advanced Scrollable Dropdown class for customtkinter widgets +Author: Akash Bora +''' + +import customtkinter +import sys +import time + +class CTkScrollableDropdown(customtkinter.CTkToplevel): + + def __init__(self, attach, x=None, y=None, button_color=None, height: int = 200, width: int = None, + fg_color=None, button_height: int = 20, justify="center", scrollbar_button_color=None, + scrollbar=True, scrollbar_button_hover_color=None, frame_border_width=2, values=[], + command=None, image_values=[], alpha: float = 0.97, frame_corner_radius=20, double_click=False, + resize=True, frame_border_color=None, text_color=None, autocomplete=False, **button_kwargs): + + super().__init__(takefocus=1) + + self.focus() + self.alpha = alpha + self.attach = attach + self.corner = frame_corner_radius + self.padding = 0 + self.focus_something = False + self.disable = True + + if sys.platform.startswith("win"): + self.after(100, lambda: self.overrideredirect(True)) + self.transparent_color = self._apply_appearance_mode(self._fg_color) + self.attributes("-transparentcolor", self.transparent_color) + elif sys.platform.startswith("darwin"): + self.overrideredirect(True) + self.transparent_color = 'systemTransparent' + self.attributes("-transparent", True) + self.focus_something = True + else: + self.overrideredirect(True) + self.transparent_color = '#000001' + self.corner = 0 + self.padding = 18 + self.withdraw() + + self.hide = True + self.attach.bind('', lambda e: self._withdraw() if not self.disable else None, add="+") + self.attach.winfo_toplevel().bind('', lambda e: self._withdraw() if not self.disable else None, add="+") + self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") + self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") + self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") + + self.attributes('-alpha', 0) + self.disable = False + self.fg_color = customtkinter.ThemeManager.theme["CTkFrame"]["fg_color"] if fg_color is None else fg_color + self.scroll_button_color = customtkinter.ThemeManager.theme["CTkScrollbar"]["button_color"] if scrollbar_button_color is None else scrollbar_button_color + self.scroll_hover_color = customtkinter.ThemeManager.theme["CTkScrollbar"]["button_hover_color"] if scrollbar_button_hover_color is None else scrollbar_button_hover_color + self.frame_border_color = customtkinter.ThemeManager.theme["CTkFrame"]["border_color"] if frame_border_color is None else frame_border_color + self.button_color = customtkinter.ThemeManager.theme["CTkFrame"]["top_fg_color"] if button_color is None else button_color + self.text_color = customtkinter.ThemeManager.theme["CTkLabel"]["text_color"] if text_color is None else text_color + + if scrollbar is False: + self.scroll_button_color = self.fg_color + self.scroll_hover_color = self.fg_color + + self.frame = customtkinter.CTkScrollableFrame(self, bg_color=self.transparent_color, fg_color=self.fg_color, + scrollbar_button_hover_color=self.scroll_hover_color, + corner_radius=self.corner, border_width=frame_border_width, + scrollbar_button_color=self.scroll_button_color, + border_color=self.frame_border_color) + self.frame._scrollbar.grid_configure(padx=3) + self.frame.pack(expand=True, fill="both") + self.dummy_entry = customtkinter.CTkEntry(self.frame, fg_color="transparent", border_width=0, height=1, width=1) + self.no_match = customtkinter.CTkLabel(self.frame, text="No Match") + self.height = height + self.height_new = height + self.width = width + self.command = command + self.fade = False + self.resize = resize + self.autocomplete = autocomplete + self.var_update = customtkinter.StringVar() + self.appear = False + + if justify.lower()=="left": + self.justify = "w" + elif justify.lower()=="right": + self.justify = "e" + else: + self.justify = "c" + + self.button_height = button_height + self.values = values + self.button_num = len(self.values) + self.image_values = None if len(image_values)!=len(self.values) else image_values + + self.resizable(width=False, height=False) + self.transient(self.master) + self._init_buttons(**button_kwargs) + + # Add binding for different ctk widgets + if double_click or self.attach.winfo_name().startswith("!ctkentry") or self.attach.winfo_name().startswith("!ctkcombobox"): + self.attach.bind('', lambda e: self._iconify(), add="+") + else: + self.attach.bind('', lambda e: self._iconify(), add="+") + + if self.attach.winfo_name().startswith("!ctkcombobox"): + self.attach._canvas.tag_bind("right_parts", "", lambda e: self._iconify()) + self.attach._canvas.tag_bind("dropdown_arrow", "", lambda e: self._iconify()) + if self.command is None: + self.command = self.attach.set + + if self.attach.winfo_name().startswith("!ctkoptionmenu"): + self.attach._canvas.bind("", lambda e: self._iconify()) + self.attach._text_label.bind("", lambda e: self._iconify()) + if self.command is None: + self.command = self.attach.set + + self.update_idletasks() + self.x = x + self.y = y + + if self.autocomplete: + self.bind_autocomplete() + + self.deiconify() + self.withdraw() + + self.attributes("-alpha", self.alpha) + + def _withdraw(self): + if self.hide is False: self.withdraw() + self.hide = True + + def _update(self, a, b, c): + self.live_update(self.attach._entry.get()) + + def bind_autocomplete(self, ): + def appear(x): + self.appear = True + + if self.attach.winfo_name().startswith("!ctkcombobox"): + self.attach._entry.configure(textvariable=self.var_update) + self.attach._entry.bind("", appear) + self.attach.set(self.values[0]) + self.var_update.trace_add('write', self._update) + + if self.attach.winfo_name().startswith("!ctkentry"): + self.attach.configure(textvariable=self.var_update) + self.attach.bind("", appear) + self.var_update.trace_add('write', self._update) + + def fade_out(self): + for i in range(100,0,-10): + if not self.winfo_exists(): + break + self.attributes("-alpha", i/100) + self.update() + time.sleep(1/100) + + def fade_in(self): + for i in range(0,100,10): + if not self.winfo_exists(): + break + self.attributes("-alpha", i/100) + self.update() + time.sleep(1/100) + + def _init_buttons(self, **button_kwargs): + self.i = 0 + self.widgets = {} + for row in self.values: + self.widgets[self.i] = customtkinter.CTkButton(self.frame, + text=row, + height=self.button_height, + fg_color=self.button_color, + text_color=self.text_color, + image=self.image_values[i] if self.image_values is not None else None, + anchor=self.justify, + command=lambda k=row: self._attach_key_press(k), **button_kwargs) + self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) + self.i+=1 + + self.hide = False + + def destroy_popup(self): + self.destroy() + self.disable = True + + def place_dropdown(self): + self.x_pos = self.attach.winfo_rootx() if self.x is None else self.x + self.attach.winfo_rootx() + self.y_pos = self.attach.winfo_rooty() + self.attach.winfo_reqheight() + 5 if self.y is None else self.y + self.attach.winfo_rooty() + self.width_new = self.attach.winfo_width() if self.width is None else self.width + + if self.resize: + if self.button_num==1: + self.height_new = self.button_height * self.button_num + 45 + else: + self.height_new = self.button_height * self.button_num + 35 + if self.height_new>self.height: + self.height_new = self.height + + self.geometry('{}x{}+{}+{}'.format(self.width_new, self.height_new, + self.x_pos, self.y_pos)) + self.fade_in() + self.attributes('-alpha', self.alpha) + self.attach.focus() + + def _iconify(self): + if self.disable: return + if self.hide: + self._deiconify() + self.focus() + self.hide = False + self.place_dropdown() + if self.focus_something: + self.dummy_entry.pack() + self.dummy_entry.focus_set() + self.after(100, self.dummy_entry.pack_forget) + else: + self.withdraw() + self.hide = True + + def _attach_key_press(self, k): + self.fade = True + if self.command: + self.command(k) + self.fade = False + self.fade_out() + self.withdraw() + self.hide = True + + def live_update(self, string=None): + if not self.appear: return + if self.disable: return + if self.fade: return + if string: + self._deiconify() + i=1 + for key in self.widgets.keys(): + s = self.widgets[key].cget("text") + if not s.startswith(string): + self.widgets[key].pack_forget() + else: + self.widgets[key].pack(fill="x", pady=2, padx=(self.padding, 0)) + i+=1 + + if i==1: + self.no_match.pack(fill="x", pady=2, padx=(self.padding, 0)) + else: + self.no_match.pack_forget() + self.button_num = i + self.place_dropdown() + + else: + self.no_match.pack_forget() + self.button_num = len(self.values) + for key in self.widgets.keys(): + self.widgets[key].destroy() + self._init_buttons() + self.place_dropdown() + + self.frame._parent_canvas.yview_moveto(0.0) + self.appear = False + + def insert(self, value, **kwargs): + self.widgets[self.i] = customtkinter.CTkButton(self.frame, + text=value, + height=self.button_height, + fg_color=self.button_color, + text_color=self.text_color, + anchor=self.justify, + command=lambda k=value: self._attach_key_press(k), **kwargs) + self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) + self.i+=1 + self.values.append(value) + + def _deiconify(self): + if len(self.values)>0: + self.deiconify() + + def popup(self, x=None, y=None): + self.x = x + self.y = y + self.hide = True + self._iconify() + + def configure(self, **kwargs): + if "height" in kwargs: + self.height = kwargs.pop("height") + self.height_new = self.height + + if "alpha" in kwargs: + self.alpha = kwargs.pop("alpha") + + if "width" in kwargs: + self.width = kwargs.pop("width") + + if "fg_color" in kwargs: + self.frame.configure(fg_color=kwargs.pop("fg_color")) + + if "values" in kwargs: + self.values = kwargs.pop("values") + self.image_values = None + for key in self.widgets.keys(): + self.widgets[key].destroy() + self._init_buttons() + + if "image_values" in kwargs: + self.image_values = kwargs.pop("image_values") + self.image_values = None if len(self.image_values)!=len(self.values) else self.image_values + if self.image_values is not None: + i=0 + for key in self.widgets.keys(): + self.widgets[key].configure(image=self.image_values[i]) + i+=1 + + if "button_color" in kwargs: + for key in self.widgets.keys(): + self.widgets[key].configure(fg_color=kwargs.pop("button_color")) + + for key in self.widgets.keys(): + self.widgets[key].configure(**kwargs) diff --git a/CTkScrollableDropdown/ctk_scrollable_dropdown_frame.py b/CTkScrollableDropdown/ctk_scrollable_dropdown_frame.py new file mode 100644 index 00000000..1bd93c2f --- /dev/null +++ b/CTkScrollableDropdown/ctk_scrollable_dropdown_frame.py @@ -0,0 +1,278 @@ +''' +Advanced Scrollable Dropdown Frame class for customtkinter widgets +Author: Akash Bora +''' + +import customtkinter +import sys + +class CTkScrollableDropdownFrame(customtkinter.CTkFrame): + + def __init__(self, attach, x=None, y=None, button_color=None, height: int = 200, width: int = None, + fg_color=None, button_height: int = 20, justify="center", scrollbar_button_color=None, + scrollbar=True, scrollbar_button_hover_color=None, frame_border_width=2, values=[], + command=None, image_values=[], double_click=False, frame_corner_radius=True, resize=True, frame_border_color=None, + text_color=None, autocomplete=False, **button_kwargs): + + super().__init__(master=attach.winfo_toplevel(), bg_color=attach.cget("bg_color")) + + self.attach = attach + self.corner = 11 if frame_corner_radius else 0 + self.padding = 0 + self.disable = True + + self.hide = True + self.attach.bind('', lambda e: self._withdraw() if not self.disable else None, add="+") + self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") + self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") + self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") + + self.disable = False + self.fg_color = customtkinter.ThemeManager.theme["CTkFrame"]["fg_color"] if fg_color is None else fg_color + self.scroll_button_color = customtkinter.ThemeManager.theme["CTkScrollbar"]["button_color"] if scrollbar_button_color is None else scrollbar_button_color + self.scroll_hover_color = customtkinter.ThemeManager.theme["CTkScrollbar"]["button_hover_color"] if scrollbar_button_hover_color is None else scrollbar_button_hover_color + self.frame_border_color = customtkinter.ThemeManager.theme["CTkFrame"]["border_color"] if frame_border_color is None else frame_border_color + self.button_color = customtkinter.ThemeManager.theme["CTkFrame"]["top_fg_color"] if button_color is None else button_color + self.text_color = customtkinter.ThemeManager.theme["CTkLabel"]["text_color"] if text_color is None else text_color + + if scrollbar is False: + self.scroll_button_color = self.fg_color + self.scroll_hover_color = self.fg_color + + self.frame = customtkinter.CTkScrollableFrame(self, fg_color=self.fg_color, bg_color=attach.cget("bg_color"), + scrollbar_button_hover_color=self.scroll_hover_color, + corner_radius=self.corner, border_width=frame_border_width, + scrollbar_button_color=self.scroll_button_color, + border_color=self.frame_border_color) + self.frame._scrollbar.grid_configure(padx=3) + self.frame.pack(expand=True, fill="both") + + if self.corner==0: + self.corner = 21 + + self.dummy_entry = customtkinter.CTkEntry(self.frame, fg_color="transparent", border_width=0, height=1, width=1) + self.no_match = customtkinter.CTkLabel(self.frame, text="No Match") + self.height = height + self.height_new = height + self.width = width + self.command = command + self.fade = False + self.resize = resize + self.autocomplete = autocomplete + self.var_update = customtkinter.StringVar() + self.appear = False + + if justify.lower()=="left": + self.justify = "w" + elif justify.lower()=="right": + self.justify = "e" + else: + self.justify = "c" + + self.button_height = button_height + self.values = values + self.button_num = len(self.values) + self.image_values = None if len(image_values)!=len(self.values) else image_values + + self._init_buttons(**button_kwargs) + + # Add binding for different ctk widgets + if double_click or self.attach.winfo_name().startswith("!ctkentry") or self.attach.winfo_name().startswith("!ctkcombobox"): + self.attach.bind('', lambda e: self._iconify(), add="+") + self.attach._entry.bind('', lambda e: self._withdraw() if not self.disable else None, add="+") + else: + self.attach.bind('', lambda e: self._iconify(), add="+") + + if self.attach.winfo_name().startswith("!ctkcombobox"): + self.attach._canvas.tag_bind("right_parts", "", lambda e: self._iconify()) + self.attach._canvas.tag_bind("dropdown_arrow", "", lambda e: self._iconify()) + + if self.command is None: + self.command = self.attach.set + + if self.attach.winfo_name().startswith("!ctkoptionmenu"): + self.attach._canvas.bind("", lambda e: self._iconify()) + self.attach._text_label.bind("", lambda e: self._iconify()) + if self.command is None: + self.command = self.attach.set + + self.x = x + self.y = y + + if self.autocomplete: + self.bind_autocomplete() + + def _withdraw(self): + if self.hide is False: self.place_forget() + self.hide = True + + def _update(self, a, b, c): + self.live_update(self.attach._entry.get()) + + def bind_autocomplete(self, ): + def appear(x): + self.appear = True + + if self.attach.winfo_name().startswith("!ctkcombobox"): + self.attach._entry.configure(textvariable=self.var_update) + self.attach.set(self.values[0]) + self.attach._entry.bind("", appear) + self.var_update.trace_add('write', self._update) + + if self.attach.winfo_name().startswith("!ctkentry"): + self.attach.configure(textvariable=self.var_update) + self.attach.bind("", appear) + self.var_update.trace_add('write', self._update) + + def _init_buttons(self, **button_kwargs): + self.i = 0 + self.widgets = {} + for row in self.values: + self.widgets[self.i] = customtkinter.CTkButton(self.frame, + text=row, + height=self.button_height, + fg_color=self.button_color, + text_color=self.text_color, + image=self.image_values[i] if self.image_values is not None else None, + anchor=self.justify, + command=lambda k=row: self._attach_key_press(k), **button_kwargs) + self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) + self.i+=1 + + self.hide = False + + def destroy_popup(self): + self.destroy() + self.disable = True + + def place_dropdown(self): + self.x_pos = self.attach.winfo_x() if self.x is None else self.x + self.attach.winfo_rootx() + self.y_pos = self.attach.winfo_y() + self.attach.winfo_reqheight() + 5 if self.y is None else self.y + self.attach.winfo_rooty() + self.width_new = self.attach.winfo_width()-45+self.corner if self.width is None else self.width + + if self.resize: + if self.button_num==1: + self.height_new = self.button_height * self.button_num + 45 + else: + self.height_new = self.button_height * self.button_num + 35 + if self.height_new>self.height: + self.height_new = self.height + + self.frame.configure(width=self.width_new, height=self.height_new) + self.place(x=self.x_pos, y=self.y_pos) + + if sys.platform.startswith("darwin"): + self.dummy_entry.pack() + self.after(100, self.dummy_entry.pack_forget()) + + self.lift() + self.attach.focus() + + def _iconify(self): + if self.disable: return + if self.hide: + self.hide = False + self.place_dropdown() + else: + self.place_forget() + self.hide = True + + def _attach_key_press(self, k): + self.fade = True + if self.command: + self.command(k) + self.fade = False + self.place_forget() + self.hide = True + + def live_update(self, string=None): + if not self.appear: return + if self.disable: return + if self.fade: return + if string: + self._deiconify() + i=1 + for key in self.widgets.keys(): + s = self.widgets[key].cget("text") + if not s.startswith(string): + self.widgets[key].pack_forget() + else: + self.widgets[key].pack(fill="x", pady=2, padx=(self.padding, 0)) + i+=1 + + if i==1: + self.no_match.pack(fill="x", pady=2, padx=(self.padding, 0)) + else: + self.no_match.pack_forget() + self.button_num = i + self.place_dropdown() + + else: + self.no_match.pack_forget() + self.button_num = len(self.values) + for key in self.widgets.keys(): + self.widgets[key].destroy() + self._init_buttons() + self.place_dropdown() + + self.frame._parent_canvas.yview_moveto(0.0) + self.appear = False + + def insert(self, value, **kwargs): + self.widgets[self.i] = customtkinter.CTkButton(self.frame, + text=value, + height=self.button_height, + fg_color=self.button_color, + text_color=self.text_color, + anchor=self.justify, + command=lambda k=value: self._attach_key_press(k), **kwargs) + self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) + self.i+=1 + self.values.append(value) + + def _deiconify(self): + if len(self.values)>0: + self.pack_forget() + + def popup(self, x=None, y=None): + self.x = x + self.y = y + self.hide = True + self._iconify() + + def configure(self, **kwargs): + if "height" in kwargs: + self.height = kwargs.pop("height") + self.height_new = self.height + + if "alpha" in kwargs: + self.alpha = kwargs.pop("alpha") + + if "width" in kwargs: + self.width = kwargs.pop("width") + + if "fg_color" in kwargs: + self.frame.configure(fg_color=kwargs.pop("fg_color")) + + if "values" in kwargs: + self.values = kwargs.pop("values") + self.image_values = None + for key in self.widgets.keys(): + self.widgets[key].destroy() + self._init_buttons() + + if "image_values" in kwargs: + self.image_values = kwargs.pop("image_values") + self.image_values = None if len(self.image_values)!=len(self.values) else self.image_values + if self.image_values is not None: + i=0 + for key in self.widgets.keys(): + self.widgets[key].configure(image=self.image_values[i]) + i+=1 + + if "button_color" in kwargs: + for key in self.widgets.keys(): + self.widgets[key].configure(fg_color=kwargs.pop("button_color")) + + for key in self.widgets.keys(): + self.widgets[key].configure(**kwargs) diff --git a/window_config.py b/window_config.py index 1e4be837..214152e0 100644 --- a/window_config.py +++ b/window_config.py @@ -12,6 +12,8 @@ from audio_utils import get_input_device_list, get_output_device_list, get_defau from audio_recorder import SelectedMicEnergyRecorder, SelectedSpeakeEnergyRecorder from languages import translation_lang, transcription_lang, selectable_languages +from CTkScrollableDropdown import CTkScrollableDropdown + class ToplevelWindowConfig(CTkToplevel): def __init__(self, parent, *args, **kwargs): @@ -61,6 +63,9 @@ class ToplevelWindowConfig(CTkToplevel): save_json(self.parent.PATH_CONFIG, "UI_SCALING", self.parent.UI_SCALING) def optionmenu_font_family_callback(self, choice): + # set choice font + self.optionmenu_font_family.set(choice) + # tab menu self.tabview_config._segmented_button.configure(font=CTkFont(family=choice)) @@ -75,6 +80,7 @@ class ToplevelWindowConfig(CTkToplevel): self.label_font_family.configure(font=CTkFont(family=choice)) self.optionmenu_font_family.configure(font=CTkFont(family=choice)) self.optionmenu_font_family._dropdown_menu.configure(font=CTkFont(family=choice)) + self.scrollableDropdown_font_family.configure(font=CTkFont(family=choice)) self.label_ui_language.configure(font=CTkFont(family=choice)) self.optionmenu_ui_language.configure(font=CTkFont(family=choice)) self.optionmenu_ui_language._dropdown_menu.configure(font=CTkFont(family=choice)) @@ -520,13 +526,21 @@ class ToplevelWindowConfig(CTkToplevel): font_families = list(tk_font.families()) self.optionmenu_font_family = CTkOptionMenu( self.tabview_config.tab(config_tab_title_ui), - values=font_families, - command=self.optionmenu_font_family_callback, variable=StringVar(value=self.parent.FONT_FAMILY), font=CTkFont(family=self.parent.FONT_FAMILY), ) self.optionmenu_font_family.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew") - self.optionmenu_font_family._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + + ## scrollableDropdown font family + self.scrollableDropdown_font_family = CTkScrollableDropdown( + self.optionmenu_font_family, + values=font_families, + justify="left", + button_color="transparent", + command=self.optionmenu_font_family_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_font_family.frame.bind("", lambda e: self.scrollableDropdown_font_family._iconify()) ## optionmenu ui language row += 1 From bb1a37f28260436cad141cd3e76a92115c428038 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Fri, 14 Jul 2023 18:26:53 +0900 Subject: [PATCH 05/10] =?UTF-8?q?scrollableDropdown=5Ffont=5Ffamily?= =?UTF-8?q?=E3=81=8B=E3=82=89=E3=83=9E=E3=82=A6=E3=82=B9=E3=82=AB=E3=83=BC?= =?UTF-8?q?=E3=82=BD=E3=83=AB=E3=81=8C=E9=9B=A2=E3=82=8C=E3=82=8B=E3=81=A8?= =?UTF-8?q?=E9=9D=9E=E8=A1=A8=E7=A4=BA=E3=81=AB=E3=81=AA=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=ABMethod=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CTkScrollableDropdown/ctk_scrollable_dropdown.py | 2 +- window_config.py | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CTkScrollableDropdown/ctk_scrollable_dropdown.py b/CTkScrollableDropdown/ctk_scrollable_dropdown.py index c54b6197..1f32541d 100644 --- a/CTkScrollableDropdown/ctk_scrollable_dropdown.py +++ b/CTkScrollableDropdown/ctk_scrollable_dropdown.py @@ -167,7 +167,7 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): def _init_buttons(self, **button_kwargs): self.i = 0 self.widgets = {} - for row in self.values: + for row in self.values: self.widgets[self.i] = customtkinter.CTkButton(self.frame, text=row, height=self.button_height, diff --git a/window_config.py b/window_config.py index 214152e0..3f2af77c 100644 --- a/window_config.py +++ b/window_config.py @@ -1,7 +1,7 @@ from time import sleep from queue import Queue from os import path as os_path -from tkinter import DoubleVar, IntVar +from tkinter import DoubleVar, IntVar from tkinter import font as tk_font import customtkinter from customtkinter import CTkToplevel, CTkTabview, CTkFont, CTkLabel, CTkSlider, CTkOptionMenu, StringVar, CTkEntry, CTkCheckBox, CTkProgressBar @@ -540,7 +540,11 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_font_family_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_font_family.frame.bind("", lambda e: self.scrollableDropdown_font_family._iconify()) + self.scrollableDropdown_font_family.bind( + "", + lambda e: self.scrollableDropdown_font_family._withdraw() if not str(e.widget).startswith(".!ctkscrollabledropdown.") else None, + add="+" + ) ## optionmenu ui language row += 1 From 41d87fbf59fb79f0732474a59f3e700a2dd14f40 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Sat, 15 Jul 2023 04:05:27 +0900 Subject: [PATCH 06/10] move ctk_scrollable_dropdown_frame.py to ./ --- CTkScrollableDropdown/__init__.py | 12 - .../ctk_scrollable_dropdown_frame.py | 278 ------------------ ..._dropdown.py => ctk_scrollable_dropdown.py | 14 +- window_config.py | 2 +- 4 files changed, 11 insertions(+), 295 deletions(-) delete mode 100644 CTkScrollableDropdown/__init__.py delete mode 100644 CTkScrollableDropdown/ctk_scrollable_dropdown_frame.py rename CTkScrollableDropdown/ctk_scrollable_dropdown.py => ctk_scrollable_dropdown.py (98%) diff --git a/CTkScrollableDropdown/__init__.py b/CTkScrollableDropdown/__init__.py deleted file mode 100644 index 8ba844b7..00000000 --- a/CTkScrollableDropdown/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -CustomTkinter Scrollable Dropdown Menu -Author: Akash Bora -License: MIT -This is a custom dropdown menu for customtkinter. -Homepage: https://github.com/Akascape/CTkScrollableDropdown -""" - -__version__ = '0.9' - -from .ctk_scrollable_dropdown import CTkScrollableDropdown -from .ctk_scrollable_dropdown_frame import CTkScrollableDropdownFrame diff --git a/CTkScrollableDropdown/ctk_scrollable_dropdown_frame.py b/CTkScrollableDropdown/ctk_scrollable_dropdown_frame.py deleted file mode 100644 index 1bd93c2f..00000000 --- a/CTkScrollableDropdown/ctk_scrollable_dropdown_frame.py +++ /dev/null @@ -1,278 +0,0 @@ -''' -Advanced Scrollable Dropdown Frame class for customtkinter widgets -Author: Akash Bora -''' - -import customtkinter -import sys - -class CTkScrollableDropdownFrame(customtkinter.CTkFrame): - - def __init__(self, attach, x=None, y=None, button_color=None, height: int = 200, width: int = None, - fg_color=None, button_height: int = 20, justify="center", scrollbar_button_color=None, - scrollbar=True, scrollbar_button_hover_color=None, frame_border_width=2, values=[], - command=None, image_values=[], double_click=False, frame_corner_radius=True, resize=True, frame_border_color=None, - text_color=None, autocomplete=False, **button_kwargs): - - super().__init__(master=attach.winfo_toplevel(), bg_color=attach.cget("bg_color")) - - self.attach = attach - self.corner = 11 if frame_corner_radius else 0 - self.padding = 0 - self.disable = True - - self.hide = True - self.attach.bind('', lambda e: self._withdraw() if not self.disable else None, add="+") - self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") - self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") - self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") - - self.disable = False - self.fg_color = customtkinter.ThemeManager.theme["CTkFrame"]["fg_color"] if fg_color is None else fg_color - self.scroll_button_color = customtkinter.ThemeManager.theme["CTkScrollbar"]["button_color"] if scrollbar_button_color is None else scrollbar_button_color - self.scroll_hover_color = customtkinter.ThemeManager.theme["CTkScrollbar"]["button_hover_color"] if scrollbar_button_hover_color is None else scrollbar_button_hover_color - self.frame_border_color = customtkinter.ThemeManager.theme["CTkFrame"]["border_color"] if frame_border_color is None else frame_border_color - self.button_color = customtkinter.ThemeManager.theme["CTkFrame"]["top_fg_color"] if button_color is None else button_color - self.text_color = customtkinter.ThemeManager.theme["CTkLabel"]["text_color"] if text_color is None else text_color - - if scrollbar is False: - self.scroll_button_color = self.fg_color - self.scroll_hover_color = self.fg_color - - self.frame = customtkinter.CTkScrollableFrame(self, fg_color=self.fg_color, bg_color=attach.cget("bg_color"), - scrollbar_button_hover_color=self.scroll_hover_color, - corner_radius=self.corner, border_width=frame_border_width, - scrollbar_button_color=self.scroll_button_color, - border_color=self.frame_border_color) - self.frame._scrollbar.grid_configure(padx=3) - self.frame.pack(expand=True, fill="both") - - if self.corner==0: - self.corner = 21 - - self.dummy_entry = customtkinter.CTkEntry(self.frame, fg_color="transparent", border_width=0, height=1, width=1) - self.no_match = customtkinter.CTkLabel(self.frame, text="No Match") - self.height = height - self.height_new = height - self.width = width - self.command = command - self.fade = False - self.resize = resize - self.autocomplete = autocomplete - self.var_update = customtkinter.StringVar() - self.appear = False - - if justify.lower()=="left": - self.justify = "w" - elif justify.lower()=="right": - self.justify = "e" - else: - self.justify = "c" - - self.button_height = button_height - self.values = values - self.button_num = len(self.values) - self.image_values = None if len(image_values)!=len(self.values) else image_values - - self._init_buttons(**button_kwargs) - - # Add binding for different ctk widgets - if double_click or self.attach.winfo_name().startswith("!ctkentry") or self.attach.winfo_name().startswith("!ctkcombobox"): - self.attach.bind('', lambda e: self._iconify(), add="+") - self.attach._entry.bind('', lambda e: self._withdraw() if not self.disable else None, add="+") - else: - self.attach.bind('', lambda e: self._iconify(), add="+") - - if self.attach.winfo_name().startswith("!ctkcombobox"): - self.attach._canvas.tag_bind("right_parts", "", lambda e: self._iconify()) - self.attach._canvas.tag_bind("dropdown_arrow", "", lambda e: self._iconify()) - - if self.command is None: - self.command = self.attach.set - - if self.attach.winfo_name().startswith("!ctkoptionmenu"): - self.attach._canvas.bind("", lambda e: self._iconify()) - self.attach._text_label.bind("", lambda e: self._iconify()) - if self.command is None: - self.command = self.attach.set - - self.x = x - self.y = y - - if self.autocomplete: - self.bind_autocomplete() - - def _withdraw(self): - if self.hide is False: self.place_forget() - self.hide = True - - def _update(self, a, b, c): - self.live_update(self.attach._entry.get()) - - def bind_autocomplete(self, ): - def appear(x): - self.appear = True - - if self.attach.winfo_name().startswith("!ctkcombobox"): - self.attach._entry.configure(textvariable=self.var_update) - self.attach.set(self.values[0]) - self.attach._entry.bind("", appear) - self.var_update.trace_add('write', self._update) - - if self.attach.winfo_name().startswith("!ctkentry"): - self.attach.configure(textvariable=self.var_update) - self.attach.bind("", appear) - self.var_update.trace_add('write', self._update) - - def _init_buttons(self, **button_kwargs): - self.i = 0 - self.widgets = {} - for row in self.values: - self.widgets[self.i] = customtkinter.CTkButton(self.frame, - text=row, - height=self.button_height, - fg_color=self.button_color, - text_color=self.text_color, - image=self.image_values[i] if self.image_values is not None else None, - anchor=self.justify, - command=lambda k=row: self._attach_key_press(k), **button_kwargs) - self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) - self.i+=1 - - self.hide = False - - def destroy_popup(self): - self.destroy() - self.disable = True - - def place_dropdown(self): - self.x_pos = self.attach.winfo_x() if self.x is None else self.x + self.attach.winfo_rootx() - self.y_pos = self.attach.winfo_y() + self.attach.winfo_reqheight() + 5 if self.y is None else self.y + self.attach.winfo_rooty() - self.width_new = self.attach.winfo_width()-45+self.corner if self.width is None else self.width - - if self.resize: - if self.button_num==1: - self.height_new = self.button_height * self.button_num + 45 - else: - self.height_new = self.button_height * self.button_num + 35 - if self.height_new>self.height: - self.height_new = self.height - - self.frame.configure(width=self.width_new, height=self.height_new) - self.place(x=self.x_pos, y=self.y_pos) - - if sys.platform.startswith("darwin"): - self.dummy_entry.pack() - self.after(100, self.dummy_entry.pack_forget()) - - self.lift() - self.attach.focus() - - def _iconify(self): - if self.disable: return - if self.hide: - self.hide = False - self.place_dropdown() - else: - self.place_forget() - self.hide = True - - def _attach_key_press(self, k): - self.fade = True - if self.command: - self.command(k) - self.fade = False - self.place_forget() - self.hide = True - - def live_update(self, string=None): - if not self.appear: return - if self.disable: return - if self.fade: return - if string: - self._deiconify() - i=1 - for key in self.widgets.keys(): - s = self.widgets[key].cget("text") - if not s.startswith(string): - self.widgets[key].pack_forget() - else: - self.widgets[key].pack(fill="x", pady=2, padx=(self.padding, 0)) - i+=1 - - if i==1: - self.no_match.pack(fill="x", pady=2, padx=(self.padding, 0)) - else: - self.no_match.pack_forget() - self.button_num = i - self.place_dropdown() - - else: - self.no_match.pack_forget() - self.button_num = len(self.values) - for key in self.widgets.keys(): - self.widgets[key].destroy() - self._init_buttons() - self.place_dropdown() - - self.frame._parent_canvas.yview_moveto(0.0) - self.appear = False - - def insert(self, value, **kwargs): - self.widgets[self.i] = customtkinter.CTkButton(self.frame, - text=value, - height=self.button_height, - fg_color=self.button_color, - text_color=self.text_color, - anchor=self.justify, - command=lambda k=value: self._attach_key_press(k), **kwargs) - self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) - self.i+=1 - self.values.append(value) - - def _deiconify(self): - if len(self.values)>0: - self.pack_forget() - - def popup(self, x=None, y=None): - self.x = x - self.y = y - self.hide = True - self._iconify() - - def configure(self, **kwargs): - if "height" in kwargs: - self.height = kwargs.pop("height") - self.height_new = self.height - - if "alpha" in kwargs: - self.alpha = kwargs.pop("alpha") - - if "width" in kwargs: - self.width = kwargs.pop("width") - - if "fg_color" in kwargs: - self.frame.configure(fg_color=kwargs.pop("fg_color")) - - if "values" in kwargs: - self.values = kwargs.pop("values") - self.image_values = None - for key in self.widgets.keys(): - self.widgets[key].destroy() - self._init_buttons() - - if "image_values" in kwargs: - self.image_values = kwargs.pop("image_values") - self.image_values = None if len(self.image_values)!=len(self.values) else self.image_values - if self.image_values is not None: - i=0 - for key in self.widgets.keys(): - self.widgets[key].configure(image=self.image_values[i]) - i+=1 - - if "button_color" in kwargs: - for key in self.widgets.keys(): - self.widgets[key].configure(fg_color=kwargs.pop("button_color")) - - for key in self.widgets.keys(): - self.widgets[key].configure(**kwargs) diff --git a/CTkScrollableDropdown/ctk_scrollable_dropdown.py b/ctk_scrollable_dropdown.py similarity index 98% rename from CTkScrollableDropdown/ctk_scrollable_dropdown.py rename to ctk_scrollable_dropdown.py index 1f32541d..8ab5296e 100644 --- a/CTkScrollableDropdown/ctk_scrollable_dropdown.py +++ b/ctk_scrollable_dropdown.py @@ -1,7 +1,13 @@ -''' +""" +CustomTkinter Scrollable Dropdown Menu +Author: Akash Bora +License: MIT +This is a custom dropdown menu for customtkinter. +Homepage: https://github.com/Akascape/CTkScrollableDropdown + Advanced Scrollable Dropdown class for customtkinter widgets Author: Akash Bora -''' +""" import customtkinter import sys @@ -16,7 +22,7 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): resize=True, frame_border_color=None, text_color=None, autocomplete=False, **button_kwargs): super().__init__(takefocus=1) - + self.transient(self.master) self.focus() self.alpha = alpha self.attach = attach @@ -93,7 +99,7 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.image_values = None if len(image_values)!=len(self.values) else image_values self.resizable(width=False, height=False) - self.transient(self.master) + # self.transient(self.master) self._init_buttons(**button_kwargs) # Add binding for different ctk widgets diff --git a/window_config.py b/window_config.py index 3f2af77c..17e5efdf 100644 --- a/window_config.py +++ b/window_config.py @@ -12,7 +12,7 @@ from audio_utils import get_input_device_list, get_output_device_list, get_defau from audio_recorder import SelectedMicEnergyRecorder, SelectedSpeakeEnergyRecorder from languages import translation_lang, transcription_lang, selectable_languages -from CTkScrollableDropdown import CTkScrollableDropdown +from ctk_scrollable_dropdown import CTkScrollableDropdown class ToplevelWindowConfig(CTkToplevel): From ba8ab43901545c44776c300bf36277b32582c19e Mon Sep 17 00:00:00 2001 From: misygauziya Date: Sat, 15 Jul 2023 04:07:12 +0900 Subject: [PATCH 07/10] =?UTF-8?q?config=E3=82=92=E8=A1=A8=E7=A4=BA?= =?UTF-8?q?=E3=81=97=E3=81=9F=E6=99=82=E3=81=AB=E6=9C=80=E5=89=8D=E9=9D=A2?= =?UTF-8?q?=E3=81=AB=E6=9D=A5=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VRCT.py | 6 ++++-- window_config.py | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/VRCT.py b/VRCT.py index 00a2fc99..7fb09bd1 100644 --- a/VRCT.py +++ b/VRCT.py @@ -328,7 +328,6 @@ class App(CTk): image=CTkImage(Image_open(os_path.join(os_path.dirname(__file__), "img", "config-icon-white.png"))) ) self.button_config.grid(row=5, column=1, padx=(5, 10), pady=(5, 5), sticky="wse") - self.config_window = None # load ui language data language_yaml_data = get_localized_text(f"{self.UI_LANGUAGE}") @@ -400,10 +399,13 @@ class App(CTk): self.config_window = ToplevelWindowConfig(self) def button_config_callback(self): - self.config_window.deiconify() self.checkbox_translation.configure(state="disabled") self.checkbox_transcription_send.configure(state="disabled") self.checkbox_transcription_receive.configure(state="disabled") + self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"]) + + self.config_window.deiconify() + self.config_window.focus_set() self.config_window.focus() def button_information_callback(self): diff --git a/window_config.py b/window_config.py index 17e5efdf..9acb8e13 100644 --- a/window_config.py +++ b/window_config.py @@ -415,6 +415,7 @@ class ToplevelWindowConfig(CTkToplevel): self.parent.checkbox_translation.configure(state="normal") self.parent.checkbox_transcription_send.configure(state="normal") self.parent.checkbox_transcription_receive.configure(state="normal") + self.parent.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) self.parent.config_window.withdraw() def entry_message_format_callback(self, event): From 931fe674a6eed24ea6922ccda940ff4c8ad0ea90 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Sat, 15 Jul 2023 04:08:16 +0900 Subject: [PATCH 08/10] =?UTF-8?q?=E3=81=99=E3=81=B9=E3=81=A6=E3=81=AEoptio?= =?UTF-8?q?nmenu=E3=81=ABCTkScrollableDropdown=E3=82=92=E8=A8=AD=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SCROLLABLE_DROPDOWNで切り替え可 --- window_config.py | 256 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 239 insertions(+), 17 deletions(-) diff --git a/window_config.py b/window_config.py index 9acb8e13..c300ce1f 100644 --- a/window_config.py +++ b/window_config.py @@ -14,10 +14,13 @@ from languages import translation_lang, transcription_lang, selectable_languages from ctk_scrollable_dropdown import CTkScrollableDropdown +SCROLLABLE_DROPDOWN = True + class ToplevelWindowConfig(CTkToplevel): def __init__(self, parent, *args, **kwargs): super().__init__(parent, *args, **kwargs) + self.withdraw() self.parent = parent # self.geometry(f"{350}x{270}") @@ -51,19 +54,22 @@ class ToplevelWindowConfig(CTkToplevel): self.parent.TRANSPARENCY = value save_json(self.parent.PATH_CONFIG, "TRANSPARENCY", self.parent.TRANSPARENCY) - def optionmenu_theme_callback(self, choice): + def optionmenu_appearance_theme_callback(self, choice): + self.optionmenu_appearance_theme.set(choice) + customtkinter.set_appearance_mode(choice) self.parent.APPEARANCE_THEME = choice save_json(self.parent.PATH_CONFIG, "APPEARANCE_THEME", self.parent.APPEARANCE_THEME) def optionmenu_ui_scaling_callback(self, choice): + self.optionmenu_ui_scaling.set(choice) + new_scaling_float = int(choice.replace("%", "")) / 100 customtkinter.set_widget_scaling(new_scaling_float) self.parent.UI_SCALING = choice save_json(self.parent.PATH_CONFIG, "UI_SCALING", self.parent.UI_SCALING) def optionmenu_font_family_callback(self, choice): - # set choice font self.optionmenu_font_family.set(choice) # tab menu @@ -174,6 +180,8 @@ class ToplevelWindowConfig(CTkToplevel): save_json(self.parent.PATH_CONFIG, "FONT_FAMILY", self.parent.FONT_FAMILY) def optionmenu_ui_language_callback(self, choice): + self.optionmenu_ui_language.set(choice) + self.withdraw() pre_language_yaml_data = get_localized_text(f"{self.parent.UI_LANGUAGE}") self.parent.UI_LANGUAGE = get_key_by_value(selectable_languages, choice) @@ -187,7 +195,7 @@ class ToplevelWindowConfig(CTkToplevel): # add tabview textbox self.parent.add_tabview_logs(language_yaml_data) self.add_tabview_config(language_yaml_data, selectable_languages) - + # 翻訳予定 # window information # try: @@ -197,6 +205,8 @@ class ToplevelWindowConfig(CTkToplevel): self.deiconify() def optionmenu_translation_translator_callback(self, choice): + self.optionmenu_translation_translator.set(choice) + if self.parent.translator.authentication(choice, self.parent.AUTH_KEYS[choice]) is False: print_textbox(self.parent.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") print_textbox(self.parent.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") @@ -226,33 +236,47 @@ class ToplevelWindowConfig(CTkToplevel): save_json(self.parent.PATH_CONFIG, "OUTPUT_TARGET_LANG", self.parent.OUTPUT_TARGET_LANG) def optionmenu_translation_input_source_language_callback(self, choice): + self.optionmenu_translation_input_source_language.set(choice) + self.parent.INPUT_SOURCE_LANG = choice save_json(self.parent.PATH_CONFIG, "INPUT_SOURCE_LANG", self.parent.INPUT_SOURCE_LANG) def optionmenu_translation_input_target_language_callback(self, choice): + self.optionmenu_translation_input_target_language.set(choice) + self.parent.INPUT_TARGET_LANG = choice save_json(self.parent.PATH_CONFIG, "INPUT_TARGET_LANG", self.parent.INPUT_TARGET_LANG) def optionmenu_translation_output_source_language_callback(self, choice): + self.optionmenu_translation_output_source_language.set(choice) + self.parent.OUTPUT_SOURCE_LANG = choice save_json(self.parent.PATH_CONFIG, "OUTPUT_SOURCE_LANG", self.parent.OUTPUT_SOURCE_LANG) def optionmenu_translation_output_target_language_callback(self, choice): + self.optionmenu_translation_output_target_language.set(choice) + self.parent.OUTPUT_TARGET_LANG = choice save_json(self.parent.PATH_CONFIG, "OUTPUT_TARGET_LANG", self.parent.OUTPUT_TARGET_LANG) def optionmenu_input_mic_host_callback(self, choice): + self.optionmenu_input_mic_host.set(choice) + self.parent.CHOICE_MIC_HOST = choice save_json(self.parent.PATH_CONFIG, "CHOICE_MIC_HOST", self.parent.CHOICE_MIC_HOST) self.optionmenu_input_mic_device.configure(values=[device["name"] for device in get_input_device_list()[self.parent.CHOICE_MIC_HOST]]) def optionmenu_input_mic_device_callback(self, choice): + self.optionmenu_input_mic_device.set(choice) + self.parent.CHOICE_MIC_DEVICE = choice save_json(self.parent.PATH_CONFIG, "CHOICE_MIC_DEVICE", self.parent.CHOICE_MIC_DEVICE) self.checkbox_input_mic_threshold_check.deselect() self.checkbox_input_mic_threshold_check_callback() def optionmenu_input_mic_voice_language_callback(self, choice): + self.optionmenu_input_mic_voice_language.set(choice) + self.parent.INPUT_MIC_VOICE_LANGUAGE = choice save_json(self.parent.PATH_CONFIG, "INPUT_MIC_VOICE_LANGUAGE", self.parent.INPUT_MIC_VOICE_LANGUAGE) @@ -312,6 +336,7 @@ class ToplevelWindowConfig(CTkToplevel): def optionmenu_input_speaker_device_callback(self, choice): speaker_device = [device for device in get_output_device_list() if device["name"] == choice][0] if get_default_output_device()["index"] == speaker_device["index"]: + self.optionmenu_input_speaker_device.set(choice) self.parent.CHOICE_SPEAKER_DEVICE = choice save_json(self.parent.PATH_CONFIG, "CHOICE_SPEAKER_DEVICE", self.parent.CHOICE_SPEAKER_DEVICE) else: @@ -320,6 +345,8 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_input_speaker_device.configure(variable=StringVar(value=self.parent.CHOICE_SPEAKER_DEVICE)) def optionmenu_input_speaker_voice_language_callback(self, choice): + self.optionmenu_input_speaker_voice_language.set(choice) + self.parent.INPUT_SPEAKER_VOICE_LANGUAGE = choice save_json(self.parent.PATH_CONFIG, "INPUT_SPEAKER_VOICE_LANGUAGE", self.parent.INPUT_SPEAKER_VOICE_LANGUAGE) @@ -489,13 +516,28 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_appearance_theme = CTkOptionMenu( self.tabview_config.tab(config_tab_title_ui), values=["Light", "Dark", "System"], - command=self.optionmenu_theme_callback, + command=self.optionmenu_appearance_theme_callback, variable=StringVar(value=self.parent.APPEARANCE_THEME), font=CTkFont(family=self.parent.FONT_FAMILY), ) self.optionmenu_appearance_theme.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew") self.optionmenu_appearance_theme._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown appearance theme + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_appearance_theme = CTkScrollableDropdown( + self.optionmenu_appearance_theme, + values=["Light", "Dark", "System"], + justify="left", + button_color="transparent", + command=self.optionmenu_appearance_theme_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_appearance_theme.frame.bind( + "", + lambda e: self.scrollableDropdown_appearance_theme._iconify(), + ) + ## optionmenu UI scaling row += 1 self.label_ui_scaling = CTkLabel( @@ -515,6 +557,21 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_ui_scaling.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew") self.optionmenu_ui_scaling._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown ui scaling + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_ui_scaling = CTkScrollableDropdown( + self.optionmenu_ui_scaling, + values=["80%", "90%", "100%", "110%", "120%"], + justify="left", + button_color="transparent", + command=self.optionmenu_ui_scaling_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_ui_scaling.frame.bind( + "", + lambda e: self.scrollableDropdown_ui_scaling._iconify(), + ) + ## optionmenu font family row += 1 self.label_font_family = CTkLabel( @@ -533,19 +590,19 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_font_family.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew") ## scrollableDropdown font family - self.scrollableDropdown_font_family = CTkScrollableDropdown( - self.optionmenu_font_family, - values=font_families, - justify="left", - button_color="transparent", - command=self.optionmenu_font_family_callback, - font=CTkFont(family=self.parent.FONT_FAMILY), - ) - self.scrollableDropdown_font_family.bind( - "", - lambda e: self.scrollableDropdown_font_family._withdraw() if not str(e.widget).startswith(".!ctkscrollabledropdown.") else None, - add="+" - ) + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_font_family = CTkScrollableDropdown( + self.optionmenu_font_family, + values=font_families, + justify="left", + button_color="transparent", + command=self.optionmenu_font_family_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_font_family.frame.bind( + "", + lambda e: self.scrollableDropdown_font_family._iconify(), + ) ## optionmenu ui language row += 1 @@ -567,6 +624,21 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_ui_language.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew") self.optionmenu_ui_language._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown ui language + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_ui_language = CTkScrollableDropdown( + self.optionmenu_ui_language, + values=selectable_languages_values, + justify="left", + button_color="transparent", + command=self.optionmenu_ui_language_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_ui_language.frame.bind( + "", + lambda e: self.scrollableDropdown_ui_language._iconify(), + ) + # tab Translation ## optionmenu translation translator row = 0 @@ -589,6 +661,21 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_translation_translator.grid(row=row, column=1, columnspan=3, padx=padx, pady=pady, sticky="nsew") self.optionmenu_translation_translator._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown translation translator + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_translation_translator = CTkScrollableDropdown( + self.optionmenu_translation_translator, + values=list(self.parent.translator.translator_status.keys()), + justify="left", + button_color="transparent", + command=self.optionmenu_translation_translator_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_translation_translator.frame.bind( + "", + lambda e: self.scrollableDropdown_translation_translator._iconify(), + ) + ## optionmenu translation input language row +=1 self.label_translation_input_language = CTkLabel( @@ -610,6 +697,21 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_translation_input_source_language.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew") self.optionmenu_translation_input_source_language._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown translation input source language + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_translation_input_source_language = CTkScrollableDropdown( + self.optionmenu_translation_input_source_language, + values=list(translation_lang[self.parent.CHOICE_TRANSLATOR].keys()), + justify="left", + button_color="transparent", + command=self.optionmenu_translation_input_source_language_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_translation_input_source_language.frame.bind( + "", + lambda e: self.scrollableDropdown_translation_input_source_language._iconify(), + ) + ## label translation input arrow self.label_translation_input_arrow = CTkLabel( self.tabview_config.tab(config_tab_title_translation), @@ -630,6 +732,21 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_translation_input_target_language.grid(row=row, column=3, columnspan=1, padx=padx, pady=pady, sticky="nsew") self.optionmenu_translation_input_target_language._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown translation input target language + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_translation_input_target_language = CTkScrollableDropdown( + self.optionmenu_translation_input_target_language, + values=list(translation_lang[self.parent.CHOICE_TRANSLATOR].keys()), + justify="left", + button_color="transparent", + command=self.optionmenu_translation_input_target_language_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_translation_input_target_language.frame.bind( + "", + lambda e: self.scrollableDropdown_translation_input_target_language._iconify(), + ) + ## optionmenu translation output language row +=1 self.label_translation_output_language = CTkLabel( @@ -651,6 +768,21 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_translation_output_source_language.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew") self.optionmenu_translation_output_source_language._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown translation output source language + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_translation_output_source_language = CTkScrollableDropdown( + self.optionmenu_translation_output_source_language, + values=list(translation_lang[self.parent.CHOICE_TRANSLATOR].keys()), + justify="left", + button_color="transparent", + command=self.optionmenu_translation_output_source_language_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_translation_output_source_language.frame.bind( + "", + lambda e: self.scrollableDropdown_translation_output_source_language._iconify(), + ) + ## label translation output arrow self.label_translation_output_arrow = CTkLabel( self.tabview_config.tab(config_tab_title_translation), @@ -671,6 +803,21 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_translation_output_target_language.grid(row=row, column=3, columnspan=1, padx=padx, pady=pady, sticky="nsew") self.optionmenu_translation_output_target_language._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown translation output target language + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_translation_output_target_language = CTkScrollableDropdown( + self.optionmenu_translation_output_target_language, + values=list(translation_lang[self.parent.CHOICE_TRANSLATOR].keys()), + justify="left", + button_color="transparent", + command=self.optionmenu_translation_output_target_language_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_translation_output_target_language.frame.bind( + "", + lambda e: self.scrollableDropdown_translation_output_target_language._iconify(), + ) + # tab Transcription ## optionmenu input mic device's host row = 0 @@ -693,6 +840,21 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_input_mic_host.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew") self.optionmenu_input_mic_host._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown input mic device's host + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_input_mic_host = CTkScrollableDropdown( + self.optionmenu_input_mic_host, + values=[host for host in get_input_device_list().keys()], + justify="left", + button_color="transparent", + command=self.optionmenu_input_mic_host_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_input_mic_host.frame.bind( + "", + lambda e: self.scrollableDropdown_input_mic_host._iconify(), + ) + ## optionmenu input mic device row += 1 self.label_input_mic_device = CTkLabel( @@ -712,6 +874,21 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_input_mic_device.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew") self.optionmenu_input_mic_device._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown input mic device + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_input_mic_device = CTkScrollableDropdown( + self.optionmenu_input_mic_device, + values=[device["name"] for device in get_input_device_list()[self.parent.CHOICE_MIC_HOST]], + justify="left", + button_color="transparent", + command=self.optionmenu_input_mic_device_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_input_mic_device.frame.bind( + "", + lambda e: self.scrollableDropdown_input_mic_device._iconify(), + ) + ## optionmenu input mic voice language row +=1 self.label_input_mic_voice_language = CTkLabel( @@ -731,6 +908,21 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_input_mic_voice_language.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew") self.optionmenu_input_mic_voice_language._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown input mic voice language + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_input_voice_language = CTkScrollableDropdown( + self.optionmenu_input_mic_voice_language, + values=list(transcription_lang.keys()), + justify="left", + button_color="transparent", + command=self.optionmenu_input_mic_voice_language_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_input_voice_language.frame.bind( + "", + lambda e: self.scrollableDropdown_input_voice_language._iconify(), + ) + ## slider input mic energy threshold row +=1 self.label_input_mic_energy_threshold = CTkLabel( @@ -883,6 +1075,21 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_input_speaker_device.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew") self.optionmenu_input_speaker_device._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown input speaker device + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_input_speaker_device = CTkScrollableDropdown( + self.optionmenu_input_speaker_device, + values=[device["name"] for device in get_output_device_list()], + justify="left", + button_color="transparent", + command=self.optionmenu_input_speaker_device_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_input_speaker_device.frame.bind( + "", + lambda e: self.scrollableDropdown_input_speaker_device._iconify(), + ) + ## optionmenu input speaker voice language row +=1 self.label_input_speaker_voice_language = CTkLabel( @@ -902,6 +1109,21 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_input_speaker_voice_language.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew") self.optionmenu_input_speaker_voice_language._dropdown_menu.configure(font=CTkFont(family=self.parent.FONT_FAMILY)) + ## scrollableDropdown input speaker voice language + if SCROLLABLE_DROPDOWN: + self.scrollableDropdown_input_speaker_voice_language = CTkScrollableDropdown( + self.optionmenu_input_speaker_voice_language, + values=list(transcription_lang.keys()), + justify="left", + button_color="transparent", + command=self.optionmenu_input_speaker_voice_language_callback, + font=CTkFont(family=self.parent.FONT_FAMILY), + ) + self.scrollableDropdown_input_speaker_voice_language.frame.bind( + "", + lambda e: self.scrollableDropdown_input_speaker_voice_language._iconify(), + ) + ## entry input speaker energy threshold row +=1 self.label_input_speaker_energy_threshold = CTkLabel( From 631fb1e6fb31a25bc8f34c83beece9d1ac2be37f Mon Sep 17 00:00:00 2001 From: misygauziya Date: Sat, 15 Jul 2023 09:42:06 +0900 Subject: [PATCH 09/10] =?UTF-8?q?=E3=82=B9=E3=82=AF=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E3=83=90=E3=83=BC=E3=81=AE=E6=B6=88=E3=81=88=E3=82=8B?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=9F=E3=83=B3=E3=82=B0=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ctk_scrollable_dropdown.py | 90 +++++++++++++++++++------------------- window_config.py | 56 ++++++++++++------------ 2 files changed, 72 insertions(+), 74 deletions(-) diff --git a/ctk_scrollable_dropdown.py b/ctk_scrollable_dropdown.py index 8ab5296e..091e92e3 100644 --- a/ctk_scrollable_dropdown.py +++ b/ctk_scrollable_dropdown.py @@ -8,29 +8,27 @@ Homepage: https://github.com/Akascape/CTkScrollableDropdown Advanced Scrollable Dropdown class for customtkinter widgets Author: Akash Bora """ - import customtkinter import sys import time class CTkScrollableDropdown(customtkinter.CTkToplevel): - + def __init__(self, attach, x=None, y=None, button_color=None, height: int = 200, width: int = None, fg_color=None, button_height: int = 20, justify="center", scrollbar_button_color=None, scrollbar=True, scrollbar_button_hover_color=None, frame_border_width=2, values=[], command=None, image_values=[], alpha: float = 0.97, frame_corner_radius=20, double_click=False, resize=True, frame_border_color=None, text_color=None, autocomplete=False, **button_kwargs): - + super().__init__(takefocus=1) self.transient(self.master) - self.focus() self.alpha = alpha self.attach = attach self.corner = frame_corner_radius self.padding = 0 self.focus_something = False self.disable = True - + if sys.platform.startswith("win"): self.after(100, lambda: self.overrideredirect(True)) self.transparent_color = self._apply_appearance_mode(self._fg_color) @@ -53,7 +51,7 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") - + self.attributes('-alpha', 0) self.disable = False self.fg_color = customtkinter.ThemeManager.theme["CTkFrame"]["fg_color"] if fg_color is None else fg_color @@ -62,11 +60,11 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.frame_border_color = customtkinter.ThemeManager.theme["CTkFrame"]["border_color"] if frame_border_color is None else frame_border_color self.button_color = customtkinter.ThemeManager.theme["CTkFrame"]["top_fg_color"] if button_color is None else button_color self.text_color = customtkinter.ThemeManager.theme["CTkLabel"]["text_color"] if text_color is None else text_color - + if scrollbar is False: self.scroll_button_color = self.fg_color self.scroll_hover_color = self.fg_color - + self.frame = customtkinter.CTkScrollableFrame(self, bg_color=self.transparent_color, fg_color=self.fg_color, scrollbar_button_hover_color=self.scroll_hover_color, corner_radius=self.corner, border_width=frame_border_width, @@ -74,6 +72,7 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): border_color=self.frame_border_color) self.frame._scrollbar.grid_configure(padx=3) self.frame.pack(expand=True, fill="both") + self.dummy_entry = customtkinter.CTkEntry(self.frame, fg_color="transparent", border_width=0, height=1, width=1) self.no_match = customtkinter.CTkLabel(self.frame, text="No Match") self.height = height @@ -85,21 +84,20 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.autocomplete = autocomplete self.var_update = customtkinter.StringVar() self.appear = False - + if justify.lower()=="left": self.justify = "w" elif justify.lower()=="right": self.justify = "e" else: self.justify = "c" - + self.button_height = button_height self.values = values self.button_num = len(self.values) self.image_values = None if len(image_values)!=len(self.values) else image_values - + self.resizable(width=False, height=False) - # self.transient(self.master) self._init_buttons(**button_kwargs) # Add binding for different ctk widgets @@ -113,47 +111,47 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.attach._canvas.tag_bind("dropdown_arrow", "", lambda e: self._iconify()) if self.command is None: self.command = self.attach.set - + if self.attach.winfo_name().startswith("!ctkoptionmenu"): self.attach._canvas.bind("", lambda e: self._iconify()) self.attach._text_label.bind("", lambda e: self._iconify()) if self.command is None: self.command = self.attach.set - + self.update_idletasks() self.x = x self.y = y if self.autocomplete: self.bind_autocomplete() - + self.deiconify() self.withdraw() - + self.attributes("-alpha", self.alpha) - + def _withdraw(self): if self.hide is False: self.withdraw() self.hide = True def _update(self, a, b, c): self.live_update(self.attach._entry.get()) - + def bind_autocomplete(self, ): def appear(x): self.appear = True - + if self.attach.winfo_name().startswith("!ctkcombobox"): self.attach._entry.configure(textvariable=self.var_update) self.attach._entry.bind("", appear) self.attach.set(self.values[0]) self.var_update.trace_add('write', self._update) - + if self.attach.winfo_name().startswith("!ctkentry"): self.attach.configure(textvariable=self.var_update) self.attach.bind("", appear) self.var_update.trace_add('write', self._update) - + def fade_out(self): for i in range(100,0,-10): if not self.winfo_exists(): @@ -161,7 +159,7 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.attributes("-alpha", i/100) self.update() time.sleep(1/100) - + def fade_in(self): for i in range(0,100,10): if not self.winfo_exists(): @@ -169,7 +167,7 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.attributes("-alpha", i/100) self.update() time.sleep(1/100) - + def _init_buttons(self, **button_kwargs): self.i = 0 self.widgets = {} @@ -184,9 +182,9 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): command=lambda k=row: self._attach_key_press(k), **button_kwargs) self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) self.i+=1 - + self.hide = False - + def destroy_popup(self): self.destroy() self.disable = True @@ -195,9 +193,9 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.x_pos = self.attach.winfo_rootx() if self.x is None else self.x + self.attach.winfo_rootx() self.y_pos = self.attach.winfo_rooty() + self.attach.winfo_reqheight() + 5 if self.y is None else self.y + self.attach.winfo_rooty() self.width_new = self.attach.winfo_width() if self.width is None else self.width - + if self.resize: - if self.button_num==1: + if self.button_num==1: self.height_new = self.button_height * self.button_num + 45 else: self.height_new = self.button_height * self.button_num + 35 @@ -208,23 +206,23 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.x_pos, self.y_pos)) self.fade_in() self.attributes('-alpha', self.alpha) - self.attach.focus() def _iconify(self): if self.disable: return if self.hide: - self._deiconify() - self.focus() - self.hide = False + self._deiconify() self.place_dropdown() if self.focus_something: self.dummy_entry.pack() self.dummy_entry.focus_set() self.after(100, self.dummy_entry.pack_forget) + self.hide = False + self.focus_set() + self.focus() else: self.withdraw() self.hide = True - + def _attach_key_press(self, k): self.fade = True if self.command: @@ -233,7 +231,7 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.fade_out() self.withdraw() self.hide = True - + def live_update(self, string=None): if not self.appear: return if self.disable: return @@ -248,14 +246,14 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): else: self.widgets[key].pack(fill="x", pady=2, padx=(self.padding, 0)) i+=1 - + if i==1: self.no_match.pack(fill="x", pady=2, padx=(self.padding, 0)) else: self.no_match.pack_forget() self.button_num = i self.place_dropdown() - + else: self.no_match.pack_forget() self.button_num = len(self.values) @@ -263,10 +261,10 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.widgets[key].destroy() self._init_buttons() self.place_dropdown() - + self.frame._parent_canvas.yview_moveto(0.0) self.appear = False - + def insert(self, value, **kwargs): self.widgets[self.i] = customtkinter.CTkButton(self.frame, text=value, @@ -278,7 +276,7 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) self.i+=1 self.values.append(value) - + def _deiconify(self): if len(self.values)>0: self.deiconify() @@ -288,28 +286,28 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.y = y self.hide = True self._iconify() - + def configure(self, **kwargs): if "height" in kwargs: self.height = kwargs.pop("height") self.height_new = self.height - + if "alpha" in kwargs: self.alpha = kwargs.pop("alpha") - + if "width" in kwargs: self.width = kwargs.pop("width") - + if "fg_color" in kwargs: self.frame.configure(fg_color=kwargs.pop("fg_color")) - + if "values" in kwargs: self.values = kwargs.pop("values") self.image_values = None for key in self.widgets.keys(): self.widgets[key].destroy() self._init_buttons() - + if "image_values" in kwargs: self.image_values = kwargs.pop("image_values") self.image_values = None if len(self.image_values)!=len(self.values) else self.image_values @@ -318,10 +316,10 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): for key in self.widgets.keys(): self.widgets[key].configure(image=self.image_values[i]) i+=1 - + if "button_color" in kwargs: for key in self.widgets.keys(): self.widgets[key].configure(fg_color=kwargs.pop("button_color")) - + for key in self.widgets.keys(): self.widgets[key].configure(**kwargs) diff --git a/window_config.py b/window_config.py index c300ce1f..c6087fbd 100644 --- a/window_config.py +++ b/window_config.py @@ -533,9 +533,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_appearance_theme_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_appearance_theme.frame.bind( + self.scrollableDropdown_appearance_theme.bind( "", - lambda e: self.scrollableDropdown_appearance_theme._iconify(), + lambda e: self.scrollableDropdown_appearance_theme._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_appearance_theme.frame._parent_frame)) else None, ) ## optionmenu UI scaling @@ -567,9 +567,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_ui_scaling_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_ui_scaling.frame.bind( + self.scrollableDropdown_ui_scaling.bind( "", - lambda e: self.scrollableDropdown_ui_scaling._iconify(), + lambda e: self.scrollableDropdown_ui_scaling._iconify() if not str(e.widget).startswith(str(self.scrollableDropdown_ui_scaling.frame._parent_frame)) else None, ) ## optionmenu font family @@ -599,9 +599,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_font_family_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_font_family.frame.bind( + self.scrollableDropdown_font_family.bind( "", - lambda e: self.scrollableDropdown_font_family._iconify(), + lambda e: self.scrollableDropdown_font_family._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_font_family.frame._parent_frame)) else None, ) ## optionmenu ui language @@ -634,9 +634,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_ui_language_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_ui_language.frame.bind( + self.scrollableDropdown_ui_language.bind( "", - lambda e: self.scrollableDropdown_ui_language._iconify(), + lambda e: self.scrollableDropdown_ui_language._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_ui_language.frame._parent_frame)) else None, ) # tab Translation @@ -671,9 +671,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_translation_translator_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_translation_translator.frame.bind( + self.scrollableDropdown_translation_translator.bind( "", - lambda e: self.scrollableDropdown_translation_translator._iconify(), + lambda e: self.scrollableDropdown_translation_translator._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_translation_translator.frame._parent_frame)) else None, ) ## optionmenu translation input language @@ -707,9 +707,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_translation_input_source_language_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_translation_input_source_language.frame.bind( + self.scrollableDropdown_translation_input_source_language.bind( "", - lambda e: self.scrollableDropdown_translation_input_source_language._iconify(), + lambda e: self.scrollableDropdown_translation_input_source_language._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_translation_input_source_language.frame._parent_frame)) else None, ) ## label translation input arrow @@ -742,9 +742,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_translation_input_target_language_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_translation_input_target_language.frame.bind( + self.scrollableDropdown_translation_input_target_language.bind( "", - lambda e: self.scrollableDropdown_translation_input_target_language._iconify(), + lambda e: self.scrollableDropdown_translation_input_target_language._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_translation_input_target_language.frame._parent_frame)) else None, ) ## optionmenu translation output language @@ -778,9 +778,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_translation_output_source_language_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_translation_output_source_language.frame.bind( + self.scrollableDropdown_translation_output_source_language.bind( "", - lambda e: self.scrollableDropdown_translation_output_source_language._iconify(), + lambda e: self.scrollableDropdown_translation_output_source_language._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_translation_output_source_language.frame._parent_frame)) else None, ) ## label translation output arrow @@ -813,9 +813,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_translation_output_target_language_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_translation_output_target_language.frame.bind( + self.scrollableDropdown_translation_output_target_language.bind( "", - lambda e: self.scrollableDropdown_translation_output_target_language._iconify(), + lambda e: self.scrollableDropdown_translation_output_target_language._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_translation_output_target_language.frame._parent_frame)) else None, ) # tab Transcription @@ -850,9 +850,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_input_mic_host_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_input_mic_host.frame.bind( + self.scrollableDropdown_input_mic_host.bind( "", - lambda e: self.scrollableDropdown_input_mic_host._iconify(), + lambda e: self.scrollableDropdown_input_mic_host._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_input_mic_host.frame._parent_frame)) else None, ) ## optionmenu input mic device @@ -884,9 +884,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_input_mic_device_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_input_mic_device.frame.bind( + self.scrollableDropdown_input_mic_device.bind( "", - lambda e: self.scrollableDropdown_input_mic_device._iconify(), + lambda e: self.scrollableDropdown_input_mic_device._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_input_mic_device.frame._parent_frame)) else None, ) ## optionmenu input mic voice language @@ -918,9 +918,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_input_mic_voice_language_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_input_voice_language.frame.bind( + self.scrollableDropdown_input_voice_language.bind( "", - lambda e: self.scrollableDropdown_input_voice_language._iconify(), + lambda e: self.scrollableDropdown_input_voice_language._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_input_voice_language.frame._parent_frame)) else None, ) ## slider input mic energy threshold @@ -1085,9 +1085,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_input_speaker_device_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_input_speaker_device.frame.bind( + self.scrollableDropdown_input_speaker_device.bind( "", - lambda e: self.scrollableDropdown_input_speaker_device._iconify(), + lambda e: self.scrollableDropdown_input_speaker_device._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_input_speaker_device.frame._parent_frame)) else None, ) ## optionmenu input speaker voice language @@ -1119,9 +1119,9 @@ class ToplevelWindowConfig(CTkToplevel): command=self.optionmenu_input_speaker_voice_language_callback, font=CTkFont(family=self.parent.FONT_FAMILY), ) - self.scrollableDropdown_input_speaker_voice_language.frame.bind( + self.scrollableDropdown_input_speaker_voice_language.bind( "", - lambda e: self.scrollableDropdown_input_speaker_voice_language._iconify(), + lambda e: self.scrollableDropdown_input_speaker_voice_language._withdraw() if not str(e.widget).startswith(str(self.scrollableDropdown_input_speaker_voice_language.frame._parent_frame)) else None, ) ## entry input speaker energy threshold From 101f2361236bf46e5af38fa7d60771fae2c034e8 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Sat, 15 Jul 2023 16:45:09 +0900 Subject: [PATCH 10/10] =?UTF-8?q?[bugfix]=E8=B5=B7=E5=8B=95=E6=99=82?= =?UTF-8?q?=E3=81=AB=E7=9E=AC=E9=96=93=E7=9A=84=E3=81=AB=E9=96=8B=E3=81=84?= =?UTF-8?q?=E3=81=A6=E9=96=89=E3=81=98=E3=81=A6=E3=81=8C=E8=A1=8C=E3=82=8F?= =?UTF-8?q?=E3=82=8C=E3=81=A6=E3=83=95=E3=82=A9=E3=83=BC=E3=82=AB=E3=82=B9?= =?UTF-8?q?=E3=81=8C=E3=83=81=E3=82=AB=E3=83=81=E3=82=AB=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=83=90=E3=82=B0=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ctk_scrollable_dropdown.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctk_scrollable_dropdown.py b/ctk_scrollable_dropdown.py index 091e92e3..81b98205 100644 --- a/ctk_scrollable_dropdown.py +++ b/ctk_scrollable_dropdown.py @@ -125,7 +125,7 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): if self.autocomplete: self.bind_autocomplete() - self.deiconify() + # self.deiconify() self.withdraw() self.attributes("-alpha", self.alpha)