TreeViewColumn 标题中的 PyGTK Entry 小部件
如何使 gtk.Entry
小部件在 gtk.TreeViewColumn
标题/标题中可聚焦或可编辑?我已经尝试过:
# Create tree-view.
treeview = gtk.TreeView()
#...
# Create column.
renderer = gtk.CellRendererText()
column = gtk.TreeViewColumn(None, renderer, text=0)
# Set column header.
header = gtk.VBox()
title = gtk.Label("Column")
header.pack_start(title)
filter = gtk.Entry()
#...
header.pack_start(filter)
header.show_all()
column.set_widget(header)
# Add column
treeview.append_column(column)
但是列标题中的 Entry 小部件不可编辑并且不会聚焦。我尝试将“clickable”设置为 True
和 False
。我在 Ubuntu 10.04 上使用 pygtk 2.21.0-0ubuntu1 和 libgtk 2.22.0-0ubuntu1。任何帮助将不胜感激。
编辑:
问题源于 GtkTreeViewColumn
标题的显示方式。标题小部件放置在 GtkAlignment
内,其父级是 GtkHBox
,其父级是 GtkButton
,其父级最终是 GtkTreeView
代码>. GtkButton
正在拦截并阻止我的 GtkEntry
获得焦点并接收鼠标输入。
How can I make a gtk.Entry
widget focusable or editable within a gtk.TreeViewColumn
header/title? I've tried this:
# Create tree-view.
treeview = gtk.TreeView()
#...
# Create column.
renderer = gtk.CellRendererText()
column = gtk.TreeViewColumn(None, renderer, text=0)
# Set column header.
header = gtk.VBox()
title = gtk.Label("Column")
header.pack_start(title)
filter = gtk.Entry()
#...
header.pack_start(filter)
header.show_all()
column.set_widget(header)
# Add column
treeview.append_column(column)
But the Entry widget in the column header is not editable and will not focus. I've tried setting 'clickable' to both True
and False
. I'm using pygtk 2.21.0-0ubuntu1 and libgtk 2.22.0-0ubuntu1 on Ubuntu 10.04. Any help would be greatly appreciated.
EDIT:
The issue stems from how a GtkTreeViewColumn
header is displayed. The header widget is placed inside a GtkAlignment
whose parent is a GtkHBox
whose parent is a GtkButton
whose parent is finally the GtkTreeView
. The GtkButton
is intercepting and preventing my GtkEntry
from being focused and receiving mouse input.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为了使
GtkEntry
在GtkTreeView
标头中可聚焦,我必须:1) 找到标头
GtkButton
。2) 将
button-press-event
信号从标头GtkButton
传播到GtkEntry
。3) 将焦点(即
focus-in-event
信号)从标题GtkButton
传播到GtkEntry
。例子:
In order to make a
GtkEntry
focusable within aGtkTreeView
header I had to:1) Find the header
GtkButton
.2) Propagate the
button-press-event
signal from the headerGtkButton
to theGtkEntry
.3) Propagate the focus (i.e.,
focus-in-event
signal) from the headerGtkButton
to theGtkEntry
.Example:
自从提出这个问题以来,API 已经不断发展,所以我想我应该发布更新的答案。 (我在处理类似问题时偶然发现了这一点,尽管在我的例子中,我试图在列标题中放置两个按钮,而不是条目。)
首先,一些背景知识。正如问题编辑中提到的,问题源于 TreeViewColumn 的结构方式。列的标题是一个 Button,当您
set_widget
时,该小部件将成为 Button 的后代。 (这很容易被忽视,因为除非您将列设置为可单击,否则标题不会像按钮一样响应。此外,文档也没有帮助,因为它似乎假设每个人都已经知道这一点。)问题的另一个原因是按钮收集事件的方式。与大多数响应事件的小部件不同,按钮在 Gdk.Window 层次结构中没有自己的位置。相反,它在实现时会创建一个特殊的事件窗口。访问此窗口的方法是特定于按钮的:get_event_window
(与更通用的get_window
和get_parent_window
不同)。该事件窗口不可见地位于 Button 上方,在事件向下传递到 Button 的任何后代之前收集事件。因此,您放置在列标题中的小部件不会接收交互所需的事件。公认的解决方案是绕过这个障碍的一种方法,这在当时是一个有价值的答案。然而,现在有一种更简单的方法。 (我应该提到,这是一个 GTK+ 问题,与所使用的语言绑定无关。就个人而言,我使用的是 C++ 绑定。我还查看了 GTK+ 源文件(C 语言),以确认这是核心 GTK+ 行为,而不是绑定的一些工件。)
1)找到标题按钮。
如果
column
是有问题的TreeViewColumn,那么用于获取按钮的API现在很简单:get_button
方法是在 3.0 版本中添加的,在提出这个问题大约六个月后被标记。这么近。2) 将事件从按钮传播到条目。
又花了四年时间(版本 3.18)才简化了这一步。关键的开发是
set_pass_through
,它可以告诉事件窗口让事件通过。正如文档所述:“在网络术语中,这将被称为‘指针事件:无’。”剩下的技巧就是时机。在实现 Button 之前不会创建事件窗口,因此按顺序连接到 Button 的
realize
信号。就是这样(没有第 3 步)。事件现在将传播到条目或您放入列标题中的任何小部件。
如果我弄乱了语法,我深表歉意;我正在从 C++ 绑定进行翻译。如果有错误,我会请求Python大师来纠正它们。
The API has evolved since this question was asked, so I thought I would post an updated answer. (I had stumbled across this while dealing with a similar issue, although in my case I was trying to put two Buttons in the column header, not an Entry.)
First, some background. As mentioned in the question's edit, the issue stems from the way a TreeViewColumn is structured. The header of the column is a Button, and when you
set_widget
, that widget becomes a descendant of the Button. (This can be easily overlooked since the header does not respond like a button unless you set the column to be clickable. Also, the documentation does not help, as it seems to assume everyone already knows this.) A further cause of the issue is the way Buttons collect events. Unlike most widgets that respond to events, a Button does not have its own spot in the Gdk.Window hierarchy. Instead, it creates a special event window when it is realized. The method for accessing this window is Button-specific:get_event_window
(distinct from the more genericget_window
andget_parent_window
). This event window sits invisibly above the Button, collecting events before they trickle down to any descendants of the Button. Hence, the widget you place in the column header does not receive the events required for interactivity.The accepted solution is one way around this obstacle, and it was a worthy answer at the time. However, there is now an easier way. (I should mention that this is a GTK+ issue, independent of the language binding being used. Personally, I was using the C++ binding. I also peeked at the GTK+ source files – in C – to confirm that this is core GTK+ behavior and not some artifact of the binding.)
1) Find the header Button.
If
column
is the TreeViewColumn in question, the API for getting the button is now simply:The
get_button
method was added in version 3.0, which was tagged about six months after this question was asked. So close.2) Propagate events from the Button to the Entry.
It took another four years (version 3.18) for this step to simplify. The key development was
set_pass_through
, which can tell the event window to let events pass through. As the documentation states: "In the terminology of the web this would be called 'pointer-events: none'."The remaining trick is one of timing. The event window is not created until the Button is realized, so connecting to the Button's
realize
signal is in order.And that's it (there is no step 3). Events will now propagate to the Entry or whatever widget you put in the column header.
My apologies if I messed up the syntax; I am translating from the C++ binding. If there are errors, I would request a kindly Python guru to correct them.
除非这不是你的答案,但我建议你使用标准和通用的方法:使用
treeview.set_search_column(COLUMN_INDEX)
,默认情况下不会显示任何条目(并使 UI 更干净),但是当用户开始输入(将焦点放在树视图上),将显示一个弹出输入条目,搜索和过滤将由 GTK 本身自动完成。如果您坚持认为搜索条目应始终可见,请使用
treeview.set_headers_visible(False)
删除树视图标头,并在树视图上方添加自定义 HBox(包含标签和条目)。Unless this is not your answer, but i suggest you to use the standard and common method: using
treeview.set_search_column(COLUMN_INDEX)
, no entry will be displayed by default (and makes UI cleaner) but when the user starts typing (with focus on that treeview) a popup input entry will be displayed, and searching and filtering will be done by GTK itself automatically.If you persist that the search entry should be always visible, remove treeview header using
treeview.set_headers_visible(False)
, and add a custom HBox (containing label and entry) above the treeview.