如何在 tkinter Python 3.7 中为组合框下拉菜单绑定按键事件

问题描述 投票:0回答:2

我想做一个功能:当单击 tkinter 中的组合框并打开下拉菜单时,当您按任意键(例如“s”)时,它会选择组合框中的第一个元素,以“s”字母开头。 但我不知道如何将它直接绑定到由组合框创建的列表框。如果我将 keyPress 事件绑定到组合框,则当下拉菜单打开时,它不会接收事件。

所以,我尝试了这样的事情:

self.combobox.bind("<KeyPress>", self.keyPressed)
但没有成功。

您能告诉我如何做到这一点吗?或者如果可能的话?

更新:小代码示例

import tkinter as tk
from tkinter import ttk

def pressed(evt):
    print ("key pressed")

f = tk.Frame();
f.grid()
c = ttk.Combobox(f,values = ["alfa","betta","gamma"])
c.grid(column = 0, row = 0)
c.bind("<KeyRelease>",pressed)
f.mainloop()
python python-3.x tkinter combobox
2个回答
2
投票

据我了解,目前Python中没有办法获取弹出菜单。而你必须通过 TCL 来做到这一点。弱点是引用的“.f.l”部分,因为它取决于内部小部件的实现。有一个组合框的示例,当您按下键盘按钮时,它将首先按字母选择项目。

from tkinter import ttk
import itertools as it

class mycombobox(ttk.Combobox):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        pd = self.tk.call('ttk::combobox::PopdownWindow', self) #get popdownWindow reference 
        lb = pd + '.f.l' #get popdown listbox
        self._bind(('bind', lb),"<KeyPress>",self.popup_key_pressed,None)

    def popup_key_pressed(self,evt):
        values = self.cget("values")
        for i in it.chain(range(self.current() + 1,len(values)),range(0,self.current())):
            if evt.char.lower() == values[i][0].lower():
                self.current(i)
                self.icursor(i)
                self.tk.eval(evt.widget + ' selection clear 0 end') #clear current selection
                self.tk.eval(evt.widget + ' selection set ' + str(i)) #select new element
                self.tk.eval(evt.widget + ' see ' + str(i)) #spin combobox popdown for selected element will be visible
                return

0
投票

根据您的代码,当键入键/字符(如“s”)时,将选择组合框中以字母开头的第一个项目(如果存在),如果选择相同的键,则选择下一个项目:

def pressed(event):
    widget = event.widget
    matching_values = [item for item in widget['values'] if item.lower().startswith(event.char.lower())]
    # Select the first matching item if available
    if matching_values:
        current_value = widget.get()
        for i, val in enumerate(matching_values):
            if current_value == val:
                break
        i = 0 if i >= len(matching_values)-1 else i+1
        widget.set(matching_values[i])  # Set the combobox to the first match
© www.soinside.com 2019 - 2024. All rights reserved.