如何从 gtk.Entry 的图标创建下拉菜单?

How to create a dropdown from a gtk.Entry's icon?

我有一个gtk.Entry,文本后面有一个图标,打算作为一个文本搜索字段:

我想要做的是在用户点击图标时显示一个下拉菜单(即 gtk.ComboBox),以选择搜索类型。该功能的模拟是:

我试过好几样东西都没有成功。例如,尝试打包一个空的 gtk.ComboBox 仅在条目之后显示一个箭头,并且仅在按下图标时将其填充,这会产生错觉,但它有两个缺点:a)当我填充 ComboBox 时,工具栏变大,并且 b) 当我清除 () ListStore 时,ComboBox 保持其宽度并留下一个丑陋的灰色框。

在这一点上,我想我需要在按下图标时创建一个 CellRenderer,它会弹出 Entry 的图标,我尝试理解 gtk.ComboBoxEntry 的代码但没有成功(在 gtkcomboboxentry.c) 中,但据我了解,它在整个作品中使用垂直容器和 CellRenderer。

GTK+3也没有这方面的想法

关于如何在 PyGTK 中创建它的任何想法或指导?

我正在寻找类似的东西,所以我想到了下面的代码。我并没有真正担心美学。我确实将元组列表传递给 MyPopup class,并希望为下拉列表中的每个菜单项传递处理程序。请注意 item.show() 是必需的,即使存在 show_all():

from gi.repository import Gtk

class MyPopup(Gtk.MenuButton):
    def __init__(self, btndefs):
        super(MyPopup, self).__init__()

        self.menu = Gtk.Menu()
        self.set_popup(self.menu)
        #self.set_label(">")
        self.set_direction(Gtk.ArrowType.RIGHT)

        for btndef in btndefs:
            item = Gtk.MenuItem()
            item.set_label(btndef[0])
            item.show()
            self.menu.append(item)

class MainWindow(Gtk.Window):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.set_size_request(100, -1)
        self.connect("destroy", lambda x: Gtk.main_quit())

        self.hbox = Gtk.Box(orientation = Gtk.Orientation.HORIZONTAL)
        self.entry = Gtk.Entry()

        self.popup = MyPopup( (("String",),
                               ("String no case",),
                               ("Hexadecimal",),
                               ("Regexp",)) )

        self.hbox.pack_start(self.entry, True, True, 0)
        self.hbox.pack_start(self.popup, False, True, 0)

        self.add(self.hbox)

        self.show_all()

    def run(self):
        Gtk.main()


def main():
    mw = MainWindow()
    mw.run()
    return 0

if __name__ == '__main__':
    main()

是的,已经晚了一年,但不要让下一个跌跌撞撞来到这里的人像我一样悲伤

这是使用Gtk.Menu() popup的例子,你也可以类似的壮举。用 Gtk.Popover()

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '3.0')

from gi.repository import Gtk, Gdk

opts = {
    'hex'     : "system-run-symbolic",
    'regex'   : "font-select-symbolic",
    'string'  : "font-x-generic-symbolic",
    'no-case' : "tools-check-spelling-symbolic",
}

def make_menu(entry, opts):
    menu = Gtk.Menu()
    for label, icon in opts.items():
        item = Gtk.MenuItem()
        item.set_label(label)
        item.connect(
            "activate",
            lambda w: entry.set_icon_from_icon_name(0, opts[w.get_label()])
        )
        menu.append(item)

        # NOTE you can use Gtk.ImageMenuItem to add image but its
        # Deprecated since version 3.10

    menu.show_all()
    return menu


def on_icon_release(widget, pos, event):
    menu = make_menu(widget, opts)
    menu.popup(
        parent_menu_shell = None,
        parent_menu_item  = None,
        func              = None,
        data              = None,
        button            = Gdk.BUTTON_PRIMARY,
        activate_time     = event.get_time()
    )

def make_entry():
    entry = Gtk.Entry()
    entry.set_icon_from_icon_name(0, 'action-unavailable-symbolic')
    entry.set_icon_from_icon_name(1, 'fonts')
    entry.set_icon_sensitive(1, True)
    entry.set_icon_activatable(1, True)
    entry.connect("icon-release", on_icon_release)
    return entry


root = Gtk.Window()
root.add(make_entry())
root.show_all()
Gtk.main()