Как мне привязать список выпадающего списка в Python Tkinter

#python #tkinter #combobox

#python #tkinter #выпадающий список

Вопрос:

Я хочу создать привязку, которая позволяет мне устанавливать определенное значение в зависимости от нажатой пользователем клавиши. Вот пример кода, в котором я это делаю:

 from tkinter import *
from tkinter import ttk

v=Tk()

combo = ttk.Combobox(values=['item1','item2','item3','item4'], state='readonly')
combo.current(0)
combo.pack()

def function(Event):
    if(Event.char in '1234'):
        combo.set(f'item{Event.char}')

combo.bind('<Key>', function)
v.mainloop()
  

Они скажут мне: «Если это сработает, что вы делаете, спрашивая об этом?»
Оказывается, что если выпадающий список развернут, привязка перестает работать.
Как можно решить проблему?


Я знаю, что эту часть вопроса задавать не следует, поскольку она не имеет никакого отношения к рассматриваемой проблеме. Но я хотел бы попросить, чтобы, если в этом вопросе что-то не так, или написано с ошибкой, или что-то еще, было сообщено. Страница «как задать хороший вопрос» мне не подходит, поскольку, с моей точки зрения, я делаю все так, как там говорят. Я сделал все возможное, чтобы сделать то, что написано здесь, как можно более подробным и понятным. Надеюсь на ваше понимание, спасибо.

Комментарии:

1. Что такое «развернуто»?

2. Я имею в виду, когда нажимается кнопка справа от выпадающего списка и ниже появляется список. Есть ли более подходящее слово? «отображаемый» работает? Спасибо за ваш вопрос!

3. Вы привязываетесь к Combobox единственному. Когда отображается список, фокус больше не на вашем Combobox , поэтому ключи не будут работать. Однако вы можете сделать v.bind_all('<Key>', function) это для всего приложения.

4. Но что, если у вас было более одного выпадающего списка? Как я могу определить, какой из двух вызывает функцию?

Ответ №1:

Основываясь на том, что предложил Генри Йик, и изучая то, что было возвращено Event.widget, я нашел решение проблемы.

 from tkinter import *
from tkinter import ttk

v=Tk()

# I create two test combobox
for _ in range(2):
    combo = ttk.Combobox(values=['item1','item2','item3','item4'], state='readonly')
    combo.current(0)
    combo.pack()

# I create a test entry to test if the function correctly recognizes when it should be executed
entrada = Entry()
entrada.pack()

def function(Event):
    """
    If Event.widget is a str and ends with ".popdown.f.l" I consider it to be the Listbox,
    I get the path of the Combobox it belongs to and convert it to a widget.
    Afterwards, I set the value of Event.widget to that of the supposed combobox.
    """
    if(isinstance(Event.widget, str) and Event.widget.endswith(".popdown.f.l")):
        Event.widget = v._nametowidget(Event.widget[:-len(".popdown.f.l")])

        
    # If Event.widget is not a Combobox, it stops the execution of the function.
    if(not isinstance(Event.widget, ttk.Combobox)):
        return

    if(Event.char in '1234'):
        Event.widget.set(f'item{Event.char}')

v.bind_all('<Key>', function)
v.mainloop()