如何检查 Gjs class 是否已定义?

How do I check that a Gjs class has already been defined?

我正在编写首选项视图 GNOME shell 扩展和使用 imports.lang 函数以面向对象的方式编写应用程序时面临的问题。

const Gtk = imports.gi.Gtk
const Lang = imports.lang
Gtk.init(null)
const MyWindow = new Lang.Class({...})

第一次打开首选项 window 有效,但后续的会抛出以下错误:Error: Type name Gjs_MyWindow is already registered。第一次关闭 window 时,我收到此错误:TypeError: prefsModule.init is not a function.

以下命令式代码有效:

const Gtk = imports.gi.Gtk
Gtk.init(null)
const window = new Gtk.Window({ type: Gtk.WindowType.TOPLEVEL })

根据抛出的错误,我的猜测是 class 正在被重新定义。否则如何避免重新定义并接收定义的 class ? (有什么文档可以参考吗?)

如果你想在 GJS 中详细了解 GObject/Gtk classes,请查看 testGObjectClass.js and testGtk.js(实际上整个目录都是黄金目录)。

如果这是 prefs.js,您需要一个名为 buildPrefsWidget() 的函数,它应该 return 一个要添加到 window 的小部件实例,而不是 Gtk.Window实例。否则,您应该定义 class:

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();

看起来正确答案在 this discussion.

If you extend a GObject class (anything from St, Clutter, Gtk, etc.), you're registering a new GType, and that's not possible for extensions.

...

Extensions are dynamic modules, and they can be loaded and unloaded - but that's not at all possible for GTypes.

所以,不要扩展 GType。相反,使用看起来像那样的“委托模式”。

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 文件中完成...

不要在这里询问更多细节,这就是我今天所知道的!