【问题标题】:Show combobox drop down while editing text using tkinter使用 tkinter 编辑文本时显示组合框下拉列表
【发布时间】:2020-05-02 22:51:40
【问题描述】:

是否可以在打开下拉菜单时使组合框可编辑? 我还没有找到任何解决方案。 我想让它更像 Google 搜索,但使用 ComboBox。

【问题讨论】:

  • 谢谢@stovfl:但我不是在寻找自动完成。我只想在打开下拉菜单时在组合框中输入任何内容。现在只要下拉菜单打开,我们就不能写任何东西。我的问题是,我们可以在下拉菜单打开时使组合框可编辑吗?意味着当我们在组合框中输入任何内容时下拉菜单将打开,即使在下拉菜单打开后我们仍然可以输入。
  • “在打开 Listbox 时输入 Entry:这超出了 Combobox 的范围。您可以通过发送.event_generate('<Button-1>') 显示Listbox,但随后Entry 会丢失Focus。如果你 Focus Entry Listbox 关闭。使用这样的东西:making-a-pop-up-keyboard-in-tkinter-with-toplevel
  • 有什么方法可以绑定“向上按钮”,这样在按下“向上按钮”时下拉菜单会关闭并且焦点会回到组合框条目?通常通过按“向上按钮” main_focus 从一个数据更改为另一个数据,但在下拉列表的顶部停止,如果我们再次按“向上按钮”然后焦点自动返回条目,有没有办法关闭下拉菜单?
  • 绑定“向上按钮”:不知道,这些Events 可用。
  • “按任意按钮”:你说的是Button,但你的意思是Keyboard Arrow Key??

标签: python tkinter combobox


【解决方案1】:

问题:在编辑文本时显示ComboboxPopdownWindow

此示例将ttk.Combobox 扩展为以下内容:

  • 键入时显示 PopdownWindow
  • 在按键'<Down>' 上打开弹出窗口
  • 如果在Listbox 中的第一项,则在按下键'<Up' 时关闭PopdownWindow

参考


  1. ttk.Combox继承

    import tkinter as tk
    import tkinter.ttk as ttk
    
    
    class Combobox(ttk.Combobox):
    
  2. 帮助函数,将内部ToplevelListbox 映射到tkinter 对象。

    警告:这使用了Tk/Tcl 内部结构,可能会更改,恕不另行通知。
    这可能仅适用于经过测试的 Tk/Tcl 版本

    def _tk(self, cls, parent):
        obj = cls(parent)
        obj.destroy()
        if cls is tk.Toplevel:
            obj._w = self.tk.call('ttk::combobox::PopdownWindow', self)
        else:
            obj._w = '{}.{}'.format(parent._w, 'f.l')
        return obj
    
  3. 初始化对象,获取内部引用并绑定到按键事件

    def __init__(self, parent, **kwargs):
        super().__init__(parent, **kwargs)
        self.popdown = self._tk(tk.Toplevel, parent)
        self.listbox = self._tk(tk.Listbox, self.popdown)
    
        self.bind("<KeyPress>", self.on_keypress, '+')
        self.listbox.bind("<Up>", self.on_keypress)
    
  4. 用于显示或隐藏 PopdownWindow 并设置键盘焦点的按键处理程序。

    def on_keypress(self, event):
        if event.widget == self:
            state = self.popdown.state()
    
            if state == 'withdrawn' \
                    and event.keysym not in ['BackSpace', 'Up']:
                self.event_generate('<Button-1>')
                self.after(0, self.focus_set)
    
            if event.keysym == 'Down':
                self.after(0, self.listbox.focus_set)
    
        else:  # self.listbox
            curselection = self.listbox.curselection()
    
            if event.keysym == 'Up' and curselection[0] == 0:
                self.popdown.withdraw()
    
    

    用法

    class App(tk.Tk):
        def __init__(self):
            super().__init__()
    
            values = ('one', 'two', 'three', 'four', 'five', 'six', 'seven')
    
            self.cb = Combobox(self, value=values)
            self.cb.grid(row=0, column=0)
    
    
    if __name__ == "__main__":
        App().mainloop()
    
    

    用 Python 测试:3.5 - 'TclVersion':8.6 'TkVersion':8.6

【讨论】:

  • 我无法理解。你能一次把完整的代码发给我吗,这将是很大的帮助。提前谢谢你。
  • @KK code at once,":从上到下复制所有代码部分并运行。
  • 在我的 Mac 上,我必须将两个 after 方法的延迟设置为至少 20 毫秒。低于此值且焦点未重置到 Entry 字段。
  • @TlsChris "MACOS" 在使用 tkinter 的某些点上表现不同。您可以尝试用.after_idle(self.... 替换而没有超时值。
  • 感谢您的建议。焦点仍然在弹出窗口上!对于我正在做的事情,即使after 延迟 100 毫秒似乎也不是问题。有多少人可以在一秒钟内输入 10 个有意义的字符?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多