4

我正在编写首选项视图 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 })

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

4

2 回答 2

2

看起来正确的答案在这个讨论中。

如果你扩展一个 GObject 类(来自 St、Clutter、Gtk 等的任何东西),你正在注册一个新的 GType,而这对于扩展是不可能的。

...

扩展是动态模块,它们可以被加载和卸载——但这对于 GTypes 来说根本不可能。

所以,不要扩展 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文件中完成...

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

于 2017-11-17T09:42:56.877 回答
0

如果您想要 GJS 中 GObject/Gtk 类的完整列表,请查看 testGObjectClass.jstestGtk.js(实际上,整个目录都是黄金)。

如果这是 for 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();
于 2017-06-26T17:40:28.623 回答