简体   繁体   English

聚焦时不设置Gtk.TreeView的选择吗?

[英]Don't set a Gtk.TreeView's selection when focusing?

The following code displays a window with a button and tree view. 以下代码显示带有按钮和树状视图的窗口。 A handle for the 'clicked' signal is attached to the button and focuses the tree view. “点击”信号的句柄连接到按钮,并聚焦树视图。 When the window is initially displayed, the tree selection has no selected items, but when the tree view receives focus, the first item is automatically selected. 最初显示窗口时,树选择没有选定的项目,但是当树视图获得焦点时,将自动选择第一个项目。 Is there a way to keep a selection from being made when the tree view receives focus? 当树形视图获得焦点时,是否有一种方法可以防止做出选择?

单击之前的窗口单击后的窗口
Before click, button has focus and tree selection has no selected items. 单击之前,按钮具有焦点,并且树选择没有选定项目。 After click, tree view has focus, but an item has been selected. 单击后,树形视图具有焦点,但是已选择一个项目。

The issue that arises from this is that I have an interface that keeps some things in sync by attaching to the 'changed' signal on the tree selection of the tree view. 由此产生的问题是,我有一个接口,通过在树视图的树选择上附加“已更改”信号来使某些事物保持同步。 When the window is displayed, depending on where the tree views are in the interface, they may receive focus by default. 显示窗口时,根据树状视图在界面中的位置,默认情况下它们可能会获得焦点。 That causes a 'changed' signal, and unexpected synchronization happens. 这会导致信号“改变”,并发生意外的同步。 It's possible to call set_can_focus(False) for all the tree views, but that: 可以为所有树视图调用set_can_focus(False) ,但是:

  1. only prevents keyboard cycling focus, not programmatic focus, and the selection still turns on with programmatic focus; 仅防止键盘循环焦点,而不能防止程序化焦点,并且选择仍以程序化焦点打开; and
  2. seems to disable the ability to deselect a selection (eg, by control-clicking on a row). 似乎禁用了取消选择的功能(例如,通过按住Control键单击一行)。

Similarly I can use grab_default to ensure that something else gets focus first when the window is displayed, but it doesn't keep a stray focus event from making an unexpected selection. 类似地,我可以使用grab_default来确保在显示窗口时其他东西首先获得焦点,但是它不会使杂散焦点事件无法做出意外选择。

Based on a posted answer that says that says that selection mode SINGLE "requires at least one item to be selected", and that that explains why an element is selected on focus, I looked more into the selection mode constants. 基于一个已发布的答案 ,该答案说选择模式SINGLE“至少需要选择一个项目”,并且这说明了为什么选择一个元素作为焦点的原因,我进一步研究了选择模式常量。 Of these, SINGLE and BROWSE seem most relevant. 其中, 浏览似乎最相关的。 The pygtk documentation, GTK Selection Mode Constants , only says that: pygtk文档GTK Selection Mode Constants只说:

gtk.SELECTION_SINGLE A single selection allowed by clicking. gtk.SELECTION_SINGLE单击可以允许单个选择。
gtk.SELECTION_BROWSE A single selection allowed by browsing with the pointer. gtk.SELECTION_BROWSE通过使用指针浏览允许的单个选择。

The GTK+3 documentation, enum GtkSelectionMode , goes into a bit more detail: GTK + 3文档枚举GtkSelectionMode更加详细:

GTK_SELECTION_SINGLE Zero or one element may be selected. GTK_SELECTION_SINGLE可以选择零个或一个元素。
GTK_SELECTION_BROWSE Exactly one element is selected. GTK_SELECTION_BROWSE恰好选择了一个元素。 In some circumstances, such as initially or during a search operation, it's possible for no element to be selected with GTK_SELECTION_BROWSE. 在某些情况下,例如最初或在搜索操作期间,可能无法使用GTK_SELECTION_BROWSE选择任何元素。 What is really enforced is that the user can't deselect a currently selected element except by selecting another element. 真正强制执行的是,用户只能通过选择另一个元素来取消选择当前选择的元素。

I don't see anything here to suggest that at least one element must be selected when the selection mode is SINGLE. 我没有看到任何建议选择模式为“单”时必须至少选择一个元素的信息。

Here's code to reproduce the window and serve as an example. 这里是重现窗口并用作示例的代码。

from gi.repository import Gtk

# A ListStore with some words
list_store = Gtk.ListStore(str)
for selection in "Can a machine think?".split():
    list_store.append([selection])

# A TreeView with a single column
tree_view = Gtk.TreeView(model=list_store)
cell_renderer = Gtk.CellRendererText()
tree_view_column = Gtk.TreeViewColumn(cell_renderer=cell_renderer,text=0,title='Words')
tree_view.append_column(tree_view_column)

# A button to focus the list
focus = Gtk.Button(label='Focus List')
focus.connect('clicked',lambda *_: tree_view.grab_focus())

# A Box to hold everything, and a Window for the Box.
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
box.add(focus)       # button on top gets initial focus
box.add(tree_view)   # tree_view below doesn't, and has no selected items 
window = Gtk.Window()
window.add(box)
window.show_all()

Gtk.main()

Looking at the source in root/gtk/gtktreeview.c for tree_view.grab_focus() , we can see that gtk_tree_view_focus_to_cursor always gets called, and selects the first element. root / gtk / gtktreeview.c中查看tree_view.grab_focus()的源 ,我们可以看到gtk_tree_view_focus_to_cursor总是被调用,并选择第一个元素。 You can work around this, in some cases, though. 不过,在某些情况下,您可以解决此问题。

This is a nasty hack. 这是一个讨厌的黑客。

It overrides the grab_focus method, stores the selection before calling grab_focus , and clears the selection afterwards if there was no selection before. 它覆盖了grab_focus方法,在调用grab_focus之前存储了选择,如果之前没有选择,则随后清除选择。

def tree_view_grab_focus():
    selection = tree_view.get_selection()
    _, selected = selection.get_selected()
    Gtk.TreeView.grab_focus(tree_view)
    if selected is None:
        selection.unselect_all()

tree_view.grab_focus = tree_view_grab_focus

Unfortunately it only applies when calling grab_focus from Python, other callers (such as GTK's keyboard navigation) don't. 不幸的是,它仅适用于从Python调用grab_focus ,而其他调用者(例如GTK的键盘导航)则不适用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM