在 PyGTK 中显示从自定义 CellRenderer 触发的 Popover 时出现分段错误

问题描述 投票:0回答:1

我创建了一个继承自

Gtk.CellRenderer
的自定义小部件,其中我定义了一个从重写的
do_active
发出的自定义信号。当我尝试在该信号的连接处理程序方法中显示
Gtk.Popover
popup()
时,出现分段错误(核心已转储)。

信号似乎工作正常,所有数据都已传递等等。只有当我尝试在此处显示新的小部件时才会发生这种情况。通过其他方法创建弹出窗口也有效。

如果我尝试显示

Gtk.Dialog
,也会发生同样的情况,但不太常见 - 每隔一段时间就会发生一次,而使用
Gtk.Popover
时,95% 的情况下都会发生。

class MyCellRenderer(Gtk.CellRenderer):

    __gproperties__ = { ... }

    __gsignals__ = {
            'clicked': (
                GObject.SignalFlags.RUN_FIRST,
                None,
                ( ... )
                )
            }

    def __init__(self):
        ...

    def do_activate(self, event, widget, path, background_area, cell_area, flags):
        ...
        self.emit('clicked', path, key, rect)
        ...


class AppWindow(Gtk.ApplicationWindow):

    def __init__(self, application):
        ...
        my_renderer = MyCellRenderer()
        my_renderer.connect('clicked', self.on_renderer_clicked)
        ...
        my_treeview_column = Gtk.TreeViewColumn('My Renderer')
        my_treeview_column.pack_start(my_renderer, True)
        my_treeview_column.add_attribute( ... )
        ...
        self.treeview.append_column(my_treeview_column)
        ...

    
    def on_renderer_clicked(self, *args):

        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        label = Gtk.Label(label='Example label')
        box.pack_start(label, True, True, 10)
        box.show_all()

        popover = Gtk.Popover()
        popover.add(box)
        popover.set_relative_to(self.treeview)    # any widget would give the same result
        popover.popup()    # segmentation fault happens here
    
    ...


我知道这曾经有效,因为我之前已经测试过。一段时间后回到(未修改的)代码,我很惊讶地看到这样的问题。这可能是某些导入模块的新版本中的错误吗?如果有,是哪一个?有什么解决问题的想法吗?

python gtk3 pygtk glib gobject
1个回答
0
投票

由于无法找到段错误背后的真正原因,我不得不采取不同的方法来实现我最初想要的。我决定放弃自定义信号,而是尝试捕获

Treeview
上的事件,然后从这里获取我需要的信息。

事实上,这可能是在 PyGtk 中显示

Popover
小部件而不是
Treeview
的首选方式,但我无法确认,因为我找不到任何示例。

上面示例中的代码现在如下所示:

class MyCellRenderer(Gtk.CellRenderer):

    __gproperties__ = { ... }
    
    def __init__(self):
        ...
    
    # custom signal is removed
    # so is do_activate() as there is no need for CellRenderer to be activatable any more


class AppWindow(Gtk.ApplicationWindow):

    def __init__(self, application):
        ...
        my_renderer = MyCellRenderer()
        # we connect the 'button-press-event' signal now
        my_renderer.connect('button-press-event', self.on_treeview_clicked) 
        ...
        my_treeview_column = Gtk.TreeViewColumn('My Renderer')
        my_treeview_column.pack_start(my_renderer, True)
        my_treeview_column.add_attribute( ... )
        ...
        self.treeview.append_column(my_treeview_column)
        ...

    
    def on_treeview_clicked(self, widget, event):
        # process only left click events
        if event.button == 1:
            # find the path and column at the point of click event
            path, column, cell_x, cell_y = widget.get_path_at_pos(int(event.x), int(event.y))
            # process only valid, selected paths for our desired column (index 1 in this example)
            if path is not None and column == widget.get_column(1) and widget.get_selection().path_is_selected(path):
                # get coordinates for clicked cell
                cell_area = widget.get_cell_area(path, column)

                box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
                label = Gtk.Label(label='Example label')
                box.pack_start(label, True, True, 10)
                box.show_all()

                popover = Gtk.Popover()
                popover.add(box)
                popover.set_relative_to(widget)
                # set popover to point to clicked cell
                popover.set_pointing_to(cell_area)
                popover.popup()
    
    ...
© www.soinside.com 2019 - 2024. All rights reserved.