GTK3中GLib定时回调函数无需多余参数的实现方案
GLib定时回调参数不匹配问题解决方案
问题原因
PyGObject绑定的GLib.Source.set_callback遵循GLib原生C API的签名要求:所有Source回调函数必须接收至少1个位置参数(用户自定义数据user_data,未指定时默认传入None)。你定义的无参函数无法接收这个自动传入的参数,因此会抛出参数数量不匹配的错误。
可选解决方案
方案1:使用占位参数接收
用Python约定俗成的单下划线_作为占位参数,明确表示该参数不需要使用,代码可读性更高:
import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GLib builder = Gtk.Builder() builder.add_from_file('test1.ui') window1 = builder.get_object('window1') class Signals: def on_window1_destroy(self, widget): Gtk.main_quit() builder.connect_signals(Signals()) # 下划线为占位参数,接收GLib自动传入的user_data,无需使用 def function1(_): print("1") # 返回GLib.SOURCE_CONTINUE即可自动重复执行定时器,无需每次新建Source return GLib.SOURCE_CONTINUE # 仅初始化一次定时器即可 source1 = GLib.timeout_source_new(1000) source1.set_callback(function1) context1 = GLib.MainContext.default() source1.attach(context1) window1.show_all() Gtk.main()
如果需要支持手动无参调用,可以用可变参数接收任意多余传入值:
def function1(*_): print("1") return GLib.SOURCE_CONTINUE
方案2:lambda包装无参函数
如果完全不想修改原有函数的参数定义,可以用lambda临时包装一层,接住GLib传入的参数后再调用无参函数:
import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GLib builder = Gtk.Builder() builder.add_from_file('test1.ui') window1 = builder.get_object('window1') class Signals: def on_window1_destroy(self, widget): Gtk.main_quit() builder.connect_signals(Signals()) # 完全无参的原有函数 def function1(): print("1") return GLib.SOURCE_CONTINUE source1 = GLib.timeout_source_new(1000) # lambda接住GLib传入的user_data参数,再调用无参函数 source1.set_callback(lambda _: function1()) context1 = GLib.MainContext.default() source1.attach(context1) window1.show_all() Gtk.main()
优化提示
你原有代码在每次回调中新建Source的写法存在冗余,会产生不必要的内存开销。定时器回调只要返回GLib.SOURCE_CONTINUE(或者直接返回True,二者等价)就会自动重复执行,返回GLib.SOURCE_REMOVE(或False)就会自动停止定时器,配合source.destroy()方法可以随时终止定时任务,完全可以满足高可控性的需求。
内容的提问来源于stack exchange,提问作者pythonlearner9001
相关产品推荐
相关产品推荐

