from os import path as os_path from PIL.Image import open as Image_open, LANCZOS from customtkinter import CTkFrame, CTkLabel, CTkImage, CTkFont def getImagePath(file_name): # root\img\file_name return os_path.join(os_path.dirname(os_path.dirname(os_path.dirname(__file__))), "img", file_name) def getImageFileFromUiUtils(file_name): # root\img\file_name img = Image_open(os_path.join(os_path.dirname(os_path.dirname(os_path.dirname(__file__))), "img", file_name)) return img def openImageKeepAspectRatio(image_file, desired_width): wpercent = (desired_width/float(image_file.size[0])) hsize = int((float(image_file.size[1])*float(wpercent))) img = image_file.resize((desired_width,hsize), LANCZOS) return (img, desired_width, hsize) def retag(tag, *args): for widget in args: widget.bindtags((tag,) + widget.bindtags()) def getLatestWidth(target_widget): target_widget.update_idletasks() return target_widget.winfo_width() def getLatestHeight(target_widget): target_widget.update_idletasks() return target_widget.winfo_height() def getLongestText(settings): max_length = max(len(item["text"]) for item in settings) max_length = 0 longest_text = "" for item in settings: if len(item["text"]) > max_length: max_length = len(item["text"]) longest_text = item["text"] return longest_text def bindEnterAndLeaveColor(target_widgets, enter_color, leave_color): for target_widget in target_widgets: target_widget.bind("", lambda e, widgets=target_widgets: [w.configure(fg_color=enter_color) for w in widgets], "+") target_widget.bind("", lambda e, widgets=target_widgets: [w.configure(fg_color=leave_color) for w in widgets], "+") def bindButtonPressColor(target_widgets, clicked_color, released_color): for target_widget in target_widgets: target_widget.bind("", lambda e, widgets=target_widgets: [w.configure(fg_color=clicked_color) for w in widgets], "+") target_widget.bind("", lambda e, widgets=target_widgets: [w.configure(fg_color=released_color) for w in widgets], "+") def bindEnterAndLeaveFunction(target_widgets, enterFunction, leaveFunction): for target_widget in target_widgets: target_widget.bind("", enterFunction, "+") target_widget.bind("", leaveFunction, "+") def bindButtonPressFunction(target_widgets, buttonPressedFunction): for target_widget in target_widgets: target_widget.bind("", buttonPressedFunction, "+") def bindButtonReleaseFunction(target_widgets, buttonReleasedFunction): for target_widget in target_widgets: target_widget.bind("", buttonReleasedFunction, "+") def bindButtonPressAndReleaseFunction(target_widgets, buttonPressedFunction, buttonReleasedFunction): for target_widget in target_widgets: target_widget.bind("", buttonPressedFunction, "+") target_widget.bind("", buttonReleasedFunction, "+") def bindButtonFunctionAndColor(target_widgets, enter_color, leave_color, clicked_color, buttonReleasedFunction): bindEnterAndLeaveColor(target_widgets, enter_color, leave_color) bindButtonPressColor(target_widgets, clicked_color, enter_color) bindButtonReleaseFunction(target_widgets, buttonReleasedFunction) def unbindEventFromActiveTabWidget(active_tab_widget): for event_name in ["", "", "", ""]: active_tab_widget.unbind(event_name) active_tab_widget.children["!ctklabel"].unbind(event_name) def _setDefaultActiveTab(active_tab_widget, active_bg_color, active_text_color): active_tab_widget.configure(fg_color=active_bg_color, cursor="") active_tab_widget.children["!ctklabel"].configure(fg_color=active_bg_color, text_color=active_text_color) unbindEventFromActiveTabWidget(active_tab_widget) def switchActiveTabAndPassiveTab(active_tab_widget, current_active_tab_widget, current_active_tab_passive_function, hovered_color, clicked_color, passive_color): active_tab_widget.configure(cursor="") unbindEventFromActiveTabWidget(active_tab_widget) rebindFunctionToTab(current_active_tab_widget, current_active_tab_passive_function, hovered_color, clicked_color, passive_color) def rebindFunctionToTab(passive_tab_widget, passive_tab_function, hovered_color, clicked_color, passive_color): passive_tab_widget.configure(cursor="hand2") bindEnterAndLeaveColor([passive_tab_widget, passive_tab_widget.children["!ctklabel"]], hovered_color, passive_color) bindButtonPressColor([passive_tab_widget, passive_tab_widget.children["!ctklabel"]], clicked_color, passive_color) bindButtonReleaseFunction([passive_tab_widget, passive_tab_widget.children["!ctklabel"]], passive_tab_function) def switchTabsColor(target_widget, tab_buttons, active_bg_color, active_text_color, passive_bg_color, passive_text_color): # Change all tabs' color to passive color at first for tab_button in tab_buttons: tab_button.configure(fg_color=passive_bg_color) tab_button.children["!ctklabel"].configure(fg_color=passive_bg_color, text_color=passive_text_color) # Then, set active color to the active tab target_widget.configure(fg_color=active_bg_color) target_widget.children["!ctklabel"].configure(fg_color=active_bg_color, text_color=active_text_color) def createButtonWithImage(parent_widget, button_fg_color, button_enter_color, button_clicked_color, button_image_file, button_image_size, button_ipadxy, button_command, corner_radius: int = 0): button_wrapper = CTkFrame(parent_widget, corner_radius=corner_radius, fg_color=button_fg_color, height=0, width=0, cursor="hand2") button_widget = CTkLabel( button_wrapper, text=None, height=0, image=CTkImage((button_image_file),size=(button_image_size,button_image_size)), ) button_widget.grid(row=0, column=0, padx=button_ipadxy, pady=button_ipadxy) bindButtonFunctionAndColor( target_widgets=[button_wrapper, button_widget], enter_color=button_enter_color, leave_color=button_fg_color, clicked_color=button_clicked_color, buttonReleasedFunction=button_command, ) return button_wrapper def createOptionMenuBox(parent_widget, optionmenu_bg_color, optionmenu_hovered_bg_color, optionmenu_clicked_bg_color, optionmenu_ipadx, optionmenu_ipady, variable, font_family, font_size, text_color, image_file, image_size, command, optionmenu_position=None, setattr_widget=None, image_widget_attr_name=None): option_menu_box = CTkFrame(parent_widget, corner_radius=4, fg_color=optionmenu_bg_color, cursor="hand2") option_menu_box.grid_columnconfigure(0, weight=1) option_menu_box.grid_rowconfigure(0, weight=1) optionmenu_label_wrapper = CTkFrame(option_menu_box, corner_radius=0, fg_color=optionmenu_bg_color) optionmenu_label_wrapper.grid(row=0, column=0, sticky="ew") LABEL_COLUMN=0 if optionmenu_position == "center": optionmenu_label_wrapper.grid_columnconfigure((0,2), weight=1) LABEL_COLUMN=1 optionmenu_label_widget = CTkLabel( optionmenu_label_wrapper, textvariable=variable, height=0, font=CTkFont(family=font_family, size=font_size, weight="normal"), text_color=text_color ) optionmenu_label_widget.grid(row=0, column=LABEL_COLUMN, padx=optionmenu_ipadx, pady=optionmenu_ipady) optionmenu_img_widget = CTkLabel( option_menu_box, text=None, corner_radius=0, height=0, image=CTkImage(image_file, size=image_size) ) if image_widget_attr_name is not None: setattr(setattr_widget, image_widget_attr_name, optionmenu_img_widget) optionmenu_img_widget.grid(row=0, column=1, padx=0, pady=0) bindEnterAndLeaveColor([optionmenu_label_wrapper, option_menu_box, optionmenu_label_widget, optionmenu_img_widget], optionmenu_hovered_bg_color, optionmenu_bg_color) bindButtonPressColor([optionmenu_label_wrapper, option_menu_box, optionmenu_label_widget, optionmenu_img_widget], optionmenu_clicked_bg_color, optionmenu_hovered_bg_color) bindButtonReleaseFunction([optionmenu_label_wrapper, option_menu_box, optionmenu_label_widget, optionmenu_img_widget], command) return option_menu_box