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

如何在MVC架构下处理Gtk.Switch的notify::active信号?

搞定Gtk.Switch notify::active信号的TypeError问题

嘿,你遇到的这个TypeError问题其实是自定义信号的签名和参数传递不匹配导致的,我来给你拆解一下问题根源和解决办法:

问题出在哪?

  1. 你在View类里定义的switch_serial_toggled自定义信号,没有声明要传递任何参数,但Controller里的_on_switch_serial_toggled函数却等着接收switch和state两个参数。
  2. 当你在View的on_switch_serial_toggled方法里触发自定义信号时,只调用了self.emit('switch_serial_toggled'),没把switch和state传过去,导致Controller的处理函数接不到足够的参数,直接报错。

修正方案

只需要两步就能解决:

  • 第一步:更新View类的__gsignals__定义,让自定义信号能传递对应的参数
  • 第二步:在触发自定义信号时,把switch和state参数一起传出去

修改后的完整代码

import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio, GObject

class Application(Gtk.Application):
    def __init__(self):
        app_id = "org.iea.etc"
        flags = Gio.ApplicationFlags.FLAGS_NONE
        super(Application, self).__init__(application_id=app_id, flags=flags)

    def do_activate(self):
        Controller(None, View(application=self))

    def do_startup(self):
        Gtk.Application.do_startup(self)

class Controller(object):
    def __init__(self, model, view):
        self._model = model
        self._view = view
        self._view.connect('switch_serial_toggled', self._on_switch_serial_toggled)
        self._view.show_all()

    def _on_switch_serial_toggled(self, switch, state):
        if switch.get_active():
            print('Switch ON')
        else:
            print('Switch OFF')

class View(Gtk.ApplicationWindow):
    # 这里修改了信号签名,声明要传递两个参数:Gtk对象和任意Python对象
    __gsignals__ = {
        'switch_serial_toggled': (GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_OBJECT, GObject.TYPE_PYOBJECT))
    }

    def __init__(self, **kw):
        super(View, self).__init__(**kw)
        self._switch_serial = Gtk.Switch()
        self._switch_serial.connect("notify::active", self.on_switch_serial_toggled)
        self.add(self._switch_serial)

    def on_switch_serial_toggled(self, switch, state):
        # emit时把接收到的switch和state一起传递出去
        self.emit('switch_serial_toggled', switch, state)

if __name__ == '__main__':
    app = Application()
    exit_status = app.run(sys.argv)
    sys.exit(exit_status)

关键修改说明

  • 在__gsignals__里,第三个元素是参数类型的元组:(GObject.TYPE_OBJECT, GObject.TYPE_PYOBJECT)分别对应Gtk.Switch实例和notify信号的state参数(GParamSpec对象)。
  • 触发信号时self.emit('switch_serial_toggled', switch, state),把原信号的参数原封不动传递给自定义信号,这样Controller的处理函数就能拿到需要的参数,不会再报错。

另外,如果你的业务逻辑里不需要state参数(毕竟可以直接通过switch.get_active()获取开关状态),也可以简化自定义信号的参数,比如只传递switch,或者不传递参数,但记得同步修改Controller的处理函数参数哦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:47:08