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