我创建了一个继承自
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
...
我知道这曾经有效,因为我之前已经测试过。一段时间后回到(未修改的)代码,我很惊讶地看到这样的问题。这可能是某些导入模块的新版本中的错误吗?如果有,是哪一个?有什么解决问题的想法吗?
由于无法找到段错误背后的真正原因,我不得不采取不同的方法来实现我最初想要的。我决定放弃自定义信号,而是尝试捕获
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()
...