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

时间:2015-01-27 15:04:27

标签: python python-3.x gtk pygtk gtk3

以下代码显示一个带有按钮和树视图的窗口。 “clicked”信号的句柄附加到按钮并聚焦树视图。最初显示窗口时,树选择没有选定的项目,但是当树视图获得焦点时,将自动选择第一个项目。有没有办法在树视图获得焦点时保持选择?

window before clicking window after clicking
点击前,按钮具有焦点,树选择没有选定项目。单击后,树视图具有焦点,但已选择一个项目。

由此产生的问题是我有一个接口通过附加树视图的树选择上的'已更改'信号来保持一些事物同步。显示窗口时,根据树视图在界面中的位置,默认情况下它们可能会获得焦点。这会导致“已更改”信号,并发生意外同步。可以为所有树视图调用 set_can_focus(False),但是:

  1. 仅防止键盘循环焦点,而不是程序化焦点,并且选择仍然以程序焦点开启;和
  2. 似乎禁用取消选择选择的功能(例如,通过按住控件单击某行)。
  3. 同样地,我可以使用 grab_default 来确保在显示窗口时首先获得其他内容的焦点,但它不会使杂散焦点事件无法进行意外选择。

    基于a posted answer表示选择模式SINGLE“需要至少选择一个项目”,并且这解释了为什么在焦点上选择了一个元素,我更多地考虑了选择模式常量。其中, SINGLE BROWSE 似乎最相关。 pygtk文档GTK Selection Mode Constants仅表示:

      

    gtk.SELECTION_SINGLE点击即可进行单项选择   gtk.SELECTION_BROWSE通过指针浏览允许单个选择。

    GTK + 3文档enum GtkSelectionMode详细介绍了一些内容:

      

    GTK_SELECTION_SINGLE可以选择零个或一个元素   GTK_SELECTION_BROWSE选择了一个元素。在一些   这种情况,例如最初或在搜索操作期间,它是   可能没有使用GTK_SELECTION_BROWSE选择任何元素。什么   真正强制的是用户无法取消选择当前   选择的元素除了选择另一个元素。

    我在这里看不到任何暗示当选择模式为SINGLE时必须至少选择一个元素。

    以下是重现窗口并作为示例的代码。

    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()
    

1 个答案:

答案 0 :(得分:1)

查看root/gtk/gtktreeview.c for tree_view.grab_focus()中的源代码,我们可以看到gtk_tree_view_focus_to_cursor总是被调用,并选择第一个元素。在某些情况下,你可以解决这个问题。

这是一个讨厌的黑客。

它会覆盖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

不幸的是,它仅适用于从Python调用grab_focus时,其他调用者(例如GTK的键盘导航)不适用。