0

我有一个Gtk.Treeview显示项目的行。我想使用按钮 1(默认行为)选择行,并且在单击按钮 3(右)时,应该会出现一个上下文菜单。这是我得到的结果:

1 - 使用connect连接到button-press-event, 工作正常,但是,由于此处理程序在默认(树视图)处理程序之前调用,行选择尚未更改,读取选定行会给出先前选择的行。

2 -connect-after用于连接到button-press-event. 但是现在我的处理程序不再被调用......好像内部处理程序以return True. 奇怪的是,双击确实会调用我的处理程序。

如何让 button-3 先更改选择,然后调用我的处理程序?

这是该程序的简短版本,取消注释标记的行以测试 1 或 2。

顺便说一句:我认为可能set_activate_on_single_click会有所帮助 - 没有运气。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
#  test_keypress.py
#
#  Copyright 2021 John Coppens <john@jcoppens.com>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#
#


import gi
gi.require_version('Gtk', '3.0')
gi.require_version('GooCanvas', '2.0')
from gi.repository import Gtk, GooCanvas

class MainWindow(Gtk.Window):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.connect("destroy", lambda x: Gtk.main_quit())
        self.set_default_size(400, 300)

        store = Gtk.ListStore(str)
        view = Gtk.TreeView(model = store)
        view.connect('button-press-event', self.on_button_pressed)         # Select one of these
        # view.connect_after('button-press-event', self.on_button_pressed) # ....
        renderer = Gtk.CellRendererText()
        col = Gtk.TreeViewColumn('Column', renderer, text = 0)
        view.append_column(col)

        store.append(('Alpha', ))
        store.append(('Beta', ))
        store.append(('Gamma', ))

        scroller = Gtk.ScrolledWindow()
        scroller.add(view)

        self.add(scroller)
        self.show_all()

    def on_button_pressed(self, view, event):
        sel = view.get_selection()
        store, selected = sel.get_selected()
        item = store[selected]
        print(event.button, item[0])

    def run(self):
        Gtk.main()


def main(args):
    mainwdw = MainWindow()
    mainwdw.run()

    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))
4

2 回答 2

1

您需要使用button-release-event事件,以便 Gtk 可以处理第一个事件。例子:

view.connect('button-release-event', self.on_button_pressed)
于 2021-05-25T11:43:32.563 回答
0

谢谢@theGtknerd- 我注意到这个方法在几个程序中被使用,但不知何故感觉并不完全正确。我喜欢事情在我采取行动时发生,而不是在我完成时。

无论如何,感谢@CompanyIRC 的建议,我解决了这样的问题(代码长度大致相同):

  • 使用 中的x, y坐标button-press-event很容易识别 中的正确行Gtk.TreeView。处理完事件后,我让默认处理程序更改选择。代码类似于:
    def on_button_pressed(self, view, event):
        path, _, _, _ = view.get_path_at_pos(int(event.x), int(event.y))
        if path:
            item = self.store[self.store.get_iter(path)]
            print(event.button, item[0])

(不确定int()s 是否必要,但get_path_at_pos指定了int参数。

_s 是虚拟变量,因为返回get_path_at_pos一个 4 元组,我只需要第一个元素。

于 2021-05-26T15:26:21.763 回答