简体   繁体   中英

ttk.Combobox - dropdown box not displaying when clicked

I'm making a Tkinter app that should create a series of comboboxes and populate them with elements from a Sqlite database. However, even after populating the values property for each combobox, there is no way to display the dropdown menu or otherwise interact with the box once the app actually launches.

I can set the Combobox.current() index prior to starting the main loop and thereby display the value at that index, but once the main loop starts there is no way to interact with the box at all. I did attempt to use a postcommand callback to populate the list but got the same result. I get no errors during the process.

Note: the following code has example data coded in to replace the DB queries. This doesn't change my results.

from tkinter import *
import tkinter.ttk as ttk

class PCFrame(Frame):

    def __init__(self, master):
        self.master = master
        super().__init__(master=master)
        self.columnconfigure(0, minsize=100, weight=1)
        self.columnconfigure(1, minsize=300, weight=3)
        self.grid()

        self.widgets = {}
        self.pc_fieldnames = ["computer name",
                              "customer name",
                              "serial",
                              "model"]
        self.init_ui()

    def init_ui(self):

        label_opts = {"column": 0, "sticky": W}
        field_opts = {"column": 1, "sticky": E + W}

        for rownum, i in enumerate(self.pc_fieldnames):
            #Callback for postcommand that didn't change my results
            def field_display_handler(self=self, fieldname=i):
                return self.field_display(fieldname)

            self.widgets[i] = {}

            self.widgets[i]["NewValue"] = StringVar(self,
                                                    value=None)
            #Values here are in the form (row_value, row_serial_num)
            #Combobox will always display the first item in 
            #each of the tuples
            self.widgets[i]["ValueTuples"] = []
            self.widgets[i]["Field"] = ttk.Combobox(self, class_="PCField",
                                    textvariable=self.widgets[i]["NewValue"],
                                    state = "normal",
                                    postcommand = field_display_handler,
                                    values = [])
            self.widgets[i]["Field"].rowname = i
            self.widgets[i]["Field"].grid(row=rownum, **field_opts)
            self.widgets[i]["Label"] = ttk.Label(self, text=i.capitalize())
            self.widgets[i]["Label"].rowname = i
            self.widgets[i]["Label"].grid(row=rownum, **label_opts)

        self.populate()
        for i in self.pc_fieldnames:
            self.field_display(i)
            self.widgets[i]["Field"].current(newindex=0)

    def populate(self, search_column = None, search_criteria = None, 
                rows=None):
        if rows == None:
            #Test values here, normally would use a DB query here
            rows = []
            for i in range(5):
                rows.append({})
                for j in self.pc_fieldnames:
                    rows[i][j] = j + " " + str(i)
        #Reinitialize, then populate, all fields
        for k, w in self.widgets.items():
            w["ValueTuples"] = []
        for row in rows:
            for key in row.keys():
                k = key.lower()
                entry = row[k] if row[k] != None else ""
                try:
                    self.widgets[k]["ValueTuples"].append(
                                                    (entry, row["serial"]))
                except KeyError:
                    if k not in self.pc_fieldnames:
                        pass
                    else:
                        raise

    def field_display(self, fieldname):
        display = []
        for i in self.widgets[fieldname]["ValueTuples"]:
            display.append(i[0])
        self.widgets[fieldname]["Field"]["values"] = display

if __name__ == "__main__":
    root = Tk()
    frame = PCFrame(root)
    root.mainloop()

The problem is that you're changing the class of the combobox. This is effectively removing all of the built-in behavior of the combobox, since the default bindings are bound to the original class name of the widget.

You need to remove class_="PCField" from the definition of the combobox, or be prepared to add all of the bindings you need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM