ttk.Combobox - раскрывающийся список не отображается при нажатии - PullRequest
0 голосов
/ 03 ноября 2019

Я создаю приложение Tkinter, которое должно создать серию комбинированных списков и заполнить их элементами из базы данных Sqlite. Однако даже после заполнения свойства values ​​для каждого выпадающего списка невозможно отобразить раскрывающееся меню или иным образом взаимодействовать с полем после фактического запуска приложения.

Я могу предварительно установить индекс Combobox.current ()запустить основной цикл и, таким образом, отобразить значение по этому индексу, но как только основной цикл запустится, вообще не будет возможности взаимодействовать с блоком. Я попытался использовать обратный вызов после команды для заполнения списка, но получил тот же результат. Я не получаю ошибок во время процесса.

Примечание: в следующем коде есть пример данных, закодированных для замены запросов к БД. Это не меняет моих результатов.

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()

1 Ответ

0 голосов
/ 03 ноября 2019

Проблема в том, что вы меняете класс комбинированного списка. Это эффективно удаляет все встроенное поведение комбинированного списка, поскольку привязки по умолчанию привязаны к исходному имени класса виджета.

Вам необходимо удалить class_="PCField" из определения в выпадающем списке или быть готовым добавить все необходимые привязки.

...