You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义Gtk.ListBoxRow类中绑定信号到Main类的按钮点击函数?

解决Gtk自定义ListBoxRow按钮绑定主类回调的问题

方法一:直接传递回调函数(简单直接)

修改CustomRow的构造函数,让它接受一个回调参数,初始化按钮时绑定该回调,并将当前行实例作为参数传入,方便主类完成移除操作。

修改后的完整代码:

from gi.repository import Gtk

class CustomRow(Gtk.ListBoxRow):
    def __init__(self, label, click_callback):
        super().__init__()
        
        self.button = Gtk.Button(label='button')
        self.label = Gtk.Label(label=label)
        
        box = Gtk.Box()
        box.add(self.button)
        box.add(self.label)
        self.add(box)
        
        # 绑定按钮点击信号,将当前行作为额外参数传给回调
        self.button.connect('clicked', click_callback, self)

class Main:
    def __init__(self):
        self.window = Gtk.Window(title="ListBox Demo")
        self.window.connect("destroy", Gtk.main_quit)
        
        self.listbox = Gtk.ListBox()
        # 创建自定义行时传入主类的回调方法
        self.listbox.add(CustomRow('First Item', self.button_clicked))
        self.listbox.add(CustomRow('Second Item', self.button_clicked))
        
        self.window.add(self.listbox)

    def button_clicked(self, widget, row):
        # widget是触发点击的按钮,row是对应的CustomRow实例
        self.listbox.remove(row)
        print(f"Removed row: {row.label.get_text()}")

if __name__ == '__main__':
    main = Main()
    main.window.show_all()
    Gtk.main()

方法二:自定义信号(低耦合,适合复用场景)

让CustomRow定义一个自定义信号,按钮点击时发出该信号,主类监听信号并处理行移除。这种方式避免CustomRow直接依赖主类,耦合度更低,便于自定义行的复用。

修改后的完整代码:

from gi.repository import Gtk, GObject

# 继承GObject.GObject以支持自定义信号
class CustomRow(Gtk.ListBoxRow, GObject.GObject):
    # 定义自定义信号,参数为当前行实例
    __gsignals__ = {
        'row-delete-request': (GObject.SignalFlags.RUN_FIRST, None, (object,))
    }

    def __init__(self, label):
        super().__init__()
        
        button = Gtk.Button(label='button')
        self.label = Gtk.Label(label=label)
        
        box = Gtk.Box()
        box.add(button)
        box.add(self.label)
        self.add(box)
        
        # 按钮点击时发出自定义信号
        button.connect('clicked', lambda _: self.emit('row-delete-request', self))

# 注册自定义类型(必须执行,否则信号无法生效)
GObject.type_register(CustomRow)

class Main:
    def __init__(self):
        self.window = Gtk.Window(title="ListBox Demo")
        self.window.connect("destroy", Gtk.main_quit)
        
        self.listbox = Gtk.ListBox()
        
        # 创建行并监听自定义信号
        row1 = CustomRow('First Item')
        row1.connect('row-delete-request', self.on_row_delete)
        self.listbox.add(row1)
        
        row2 = CustomRow('Second Item')
        row2.connect('row-delete-request', self.on_row_delete)
        self.listbox.add(row2)
        
        self.window.add(self.listbox)

    def on_row_delete(self, row, *args):
        self.listbox.remove(row)
        print(f"Removed row: {row.label.get_text()}")

if __name__ == '__main__':
    main = Main()
    main.window.show_all()
    Gtk.main()

方法对比

  • 方法一:代码简洁,适合小型项目或简单场景;缺点是CustomRow与主类直接绑定,不利于自定义行的独立复用。
  • 方法二:解耦性强,CustomRow可独立用于其他场景;代码稍复杂,但扩展性和复用性更好。

内容的提问来源于stack exchange,提问作者user_968563

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 16:10:31