我正在编写首选项视图GNOME shell扩展,并且在使用imports.lang
函数以面向对象的方式编写应用程序时会遇到问题。
const Gtk = imports.gi.Gtk
const Lang = imports.lang
Gtk.init(null)
const MyWindow = new Lang.Class({...})
首次打开首选项窗口,但后续的会抛出以下错误:Error: Type name Gjs_MyWindow is already registered
。在第一次关闭窗口时,我收到此错误:TypeError: prefsModule.init is not a function
。
以下更强制性的代码有效:
const Gtk = imports.gi.Gtk
Gtk.init(null)
const window = new Gtk.Window({ type: Gtk.WindowType.TOPLEVEL })
基于抛出的错误,我的猜测是该类正在被重新定义。如何避免重新定义并接收定义的类别? (我可以参考哪些文档?)
答案 0 :(得分:1)
看起来正确答案在this discussion。
如果你扩展一个GObject类(St,Clutter,Gtk等等),那么你正在注册一个新的GType,而这对扩展来说是不可能的。
...
扩展是动态模块,它们可以加载和卸载 - 但这对GType来说根本不可能。
所以,不要扩展GTypes。相反,使用“委托模式”,看起来像这样。
const Class = new Lang.Class({
Name: "Class",
_init: function() {
this.actor = new St.Button();
}
)};
这就是说,如果您查看系统上安装的扩展并执行grep -rn 'Extends: Gtk' /usr/share/gnome-shell/extensions/
之类的操作,您会发现某些扩展仍然会扩展GType,并且不会导致任何错误。但是你会发现它永远不会在extension.js
文件中完成......
不要在这里询问更多细节,这就是我今天所知道的全部细节!
答案 1 :(得分:0)
如果你想在GJS中坚持GObject / Gtk类,请检查testGObjectClass.js和testGtk.js(实际上整个目录都是黄金)。
如果这是prefs.js
,则需要一个名为buildPrefsWidget()
的函数,该函数应返回要添加到窗口的窗口小部件实例,而不是Gtk.Window实例。否则,您应该定义您的班级:
const MyWindow = new Lang.Class({
Name: "MyWindow",
Extends: Gtk.Window,
_init: function (params) {
this.parent(params);
...
}
});
然后在定义之后,创建一个实例并使用它:
Gtk.init(null);
let window = new MyWindow({ type: Gtk.WindowType.TOPLEVEL });
window.show_all();
Gtk.main();