为什么我的 <<ComboboxSelected>> 绑定不适用于自定义 tkinter 组合框?

Why does not my <<ComboboxSelected>> binding work with custom tkinter combo boxes?

提问人:Govind 提问时间:11/12/2023 最后编辑:ThingamabobsGovind 更新时间:11/13/2023 访问量:69

问:

在我的代码中,我正在尝试允许用户单击组合框。当他们单击该框时,它将显示我的数据库中保存的类名(该部分有效)。但是,我有一个名为“class_id”的函数,它似乎没有被调用。我通过使用绑定来称呼它:“<>。此绑定适用于普通的 tkinter 组合框,但不适用于自定义 tkinter。

由于未调用函数,因此未打印类 ID。

这是我的代码(这是一个更大的程序的一部分):

#making use of a nested class
    #'renaming class' is a functionality that belongs to the 'Classes' class so I made use of a nested class
    #'Rename_ Class_Details' is the child class inheriting from the 'Classes' class  
    class Rename_Class_Details:
        def __init__(self,parent):
            #function is called to create the frame for creating a class
            self.parent = parent
            
            self.rename_class()#calling function

        def rename_class(self):
            #function packs all labels etc for user to select which class they would like to update
            self.update_class_frame = ctk.CTkFrame(self.parent.classFrame)
            self.update_class_frame.place(relx=0.4,rely=0.3)

            #giving title to frame so that user knows what its purpose is
            self.update_description = ctk.CTkLabel(
                self.update_class_frame,
                text="Rename Class",
                font=ctk.CTkFont(size=20, weight="bold")
            )
            self.update_description.grid(row=0,column=0)

            self.rename_class_label = ctk.CTkLabel(self.update_class_frame, text="Class:")
            self.rename_class_label.grid(row=1,column=0)
            self.rename_class_options = ctk.CTkComboBox(self.update_class_frame, state="readonly")
            self.rename_class_options.grid(row=1,column=1)
            self.rename_class_options.bind("<Button-1>", self.showing_classes)#binding button to function
            self.rename_class_options.bind("<<ComboBoxSelected>>", self.class_id)#binding selected input to function

            self.change_name_label = ctk.CTkLabel(self.update_class_frame, text="Change name to:")
            self.change_name_label.grid(row=2,column=0)
            self.change_name_entry = ctk.CTkEntry(self.update_class_frame)
            self.change_name_entry.grid(row=2,column=1)

            self.rename_btn = ctk.CTkButton(self.update_class_frame, text="Update Name")
            self.rename_btn.grid(row=3,column=1)
           # self.rename_btn.bind("<Button-1>", self.update_name)#binding button to function

            for widget in self.update_class_frame.winfo_children():
                widget.grid_configure(padx=10, pady=10)
                #for loop that loops through all widgets
                #assinging all widgets with same amount of padding

        def showing_classes(self,event):
            #function is called so that combobox shows all classes for user to select from
            connection = sqlite3.connect("Teacher.db")
            cursor = connection.cursor()

            checking_table_existence = """SELECT name from sqlite_master WHERE type='table' AND name='Classes'"""
            cursor.execute(checking_table_existence)
            exists = cursor.fetchone()

            if exists:
                optionSelectingClasses= [] #holds all classes in a list

                classTable = "SELECT [Class Name] FROM Classes"
                cursor.execute(classTable)

                selectTestClasses = cursor.fetchall()#fetches all fields within specified column

                #for loop that loops through all fields within column and adds entries into 'optionSelectingClasses' variable as a list
                for a in selectTestClasses:
                    optionSelectingClasses.append(str(a[0]))
                print(optionSelectingClasses)#seeing if all classes show

                self.rename_class_options.configure(values=optionSelectingClasses)
                #Combobox now shows all values (class names) within the 'Class Name' compile
                
            else:
                messagebox.showerror("Error", "There are no classes to select from!") 

        def class_id(self,event):
            #function is called so that when the user selects a class it retrieves it class ID
            connection = sqlite3.connect("Teacher.db")
            cursor = connection.cursor()

            class_selection = self.rename_class_options.get()

            selecting_class = """SELECT [Class Name], [ClassID] from Classes"""
            cursor.execute(selecting_class)
            classRecords = cursor.fetchall()

            for i in classRecords:
                if class_selection == i[0]:
                    self.classID = i[1]
            print(self.classID)#printing to see if correct ID is printed

类确实显示,但未打印类 ID。原因是因为该函数首先没有被调用。该函数适用于“ttk”,但不适用于 CTk(自定义 tkinter)。

Python Tkinter 项目

评论


答:

1赞 acw1668 11/13/2023 #1

请注意,它不继承自 ,因此它不会生成虚拟事件(另请注意它不是)。customtkinter.CTkComboBoxttk.Combobox<<ComboboxSelected>><<ComboBoxSelected>>

但是,您可以使用选项来获得类似的效果:commandcustomtkinter.CTkComboBox

def rename_class(self):
    ...
    self.rename_class_options = ctk.CTkComboBox(self.update_class_frame, state="readonly",
                                                command=self.class_id)
    ...
    # binding not needed
    #self.rename_class_options.bind("<<ComboBoxSelected>>", self.class_id)#binding selected input to function
    ...

def class_id(self, class_selection):
    #function is called so that when the user selects a class it retrieves it class ID
    connection = sqlite3.connect("Teacher.db")
    cursor = connection.cursor()

    # the selected value will be passed as argument
    # so don't need to get it here
    #class_selection = self.rename_class_options.get()

    selecting_class = """SELECT [Class Name], [ClassID] from Classes"""
    cursor.execute(selecting_class)
    classRecords = cursor.fetchall()

    for i in classRecords:
        if class_selection == i[0]:
            self.classID = i[1]
            print(self.classID)#printing to see if correct ID is printed