tkinter combobox получить id выбранного элемента

Рейтинг: 0Ответов: 2Опубликовано: 16.08.2023

Пытаюсь вывести в combobox данные из таблицы БД, в базе стоит поле id, name, мне необходимо вывести name в Combobox и получить id выбранного элемента для вставки в базу данных, т.к таблицы у меня связные. в c# это делается с помощью метода ValueMember и DisplayMember получит id combobox.SelectedValue, как это сделать в python. прощу помощи!

def getCars():
    all_data = []
    query = "SELECT name FROM cars"
    mycursor.execute(query)
    all_data = list(mycursor)
    return all_data

carscombobox = ttk.Combobox(screen, values=getCars())

mycursor.execute("insert into employees(name,surname,mobile, carsid) values(%s,%s,%s,%s)", 
(nameEntry.get(), surnameEntry.get(), mobileEntry.get(), carscombobox.get()))
con.commit()

Ответы

▲ 0Принят

Стандартный Combobox не умеет хранить ничего кроме строк. Какие-то сложные объекты (из которых, например, можно было бы получить id) в него добавить нельзя. Приходится городить костыли с отдельным списком объектов, из комбо получать индекс выбранного элемента, по индексу брать объект из списка. Пример реализации - в этом ответе.

Пример с машинами:

import tkinter as tk
from tkinter import ttk


class Car:
    def __init__(self, id, name):
        self.id = id
        self.name = name
   
    def __str__(self):
        return self.name


def get_cars() -> list[Car]:
    # query = "SELECT id, name FROM cars"  # Чтобы был доступен id, нужно его тоже селектить
    # mycursor.execute(query)
    mycursor = [(1, "Первая машина"), (2, "Вторая машина")]  # Для демонстрации просто создаю список
    all_data = [Car(id, name) for id, name in mycursor]
    return all_data


class MyCombo(ttk.Combobox):
    def __init__(self, *args, values=None, **kwargs):
        super().__init__(*args, values=values, **kwargs)
        if values is None:
            values = []
        self._values = values
    
    def get(self):
        if self.current() == -1:
            return None   # Если ничего не выбрано, возвращаем None
        else:
            return self._values[self.current()]



def show_selected_car():
    value = carscombobox.get()
    if not value:
        label.config(text="Ничего не выбрано")
    else:
        label.config(text=f"Выбрана машина {value.name} с id={value.id}")



screen = tk.Tk()

carscombobox = MyCombo(screen, values=get_cars())
carscombobox.pack()

btn1 = tk.Button(screen, text="Расчет", command=show_selected_car)
btn1.pack()

label = tk.Label(screen, text="Выберите машину")
label.pack()

screen.mainloop()

Вывод после выбора машины в комбо и нажатия на кнопку:

Скриншот

Ваш код вставки insert into employees нужно добавить в обработчик кнопки (чтобы он выполнялся после выбора чего-то в комбобоксе, а не сразу после его создания). Соответственно, id получаете через carscombobox.get().id (но желательно все-таки проверять, что что-то выбрано).

Можно сделать более "навороченную" реализацию комбобокса с корректной типизацией, чтобы mypy и IDE понимали тип возвращенного значения, пример тут: TypedCombobox

▲ 0

combo.get() - вернет значение, combo.current() - вернет индекс