【发布时间】:2020-02-12 21:58:41
【问题描述】:
我希望在我的 Gtk3 窗口关闭后执行一些代码。我试过delete-event、destroy 和destroy-event 似乎根本没有触发。
我知道 Gdk 和 Gtk 之间存在一些差异,但我不确定那是什么。我想我问的是正确的事情。
我正在使用gtk_window_new() 的node.js 绑定创建窗口,并使用gtk_window_close() 关闭它。这样做并使用上述事件时,事件处理程序会在窗口仍在屏幕上时触发。
编辑:
根据要求,一些示例代码:
const gi = require('node-gtk')
const Gtk = gi.require('Gtk', '3.0');
gi.startLoop();
Gtk.init();
const win = new Gtk.Window();
win.on('destroy', () => Gtk.mainQuit());
win.on('delete-event', () => false);
const button = new Gtk.Button({ label: 'Do it' });
win.add(button);
button.on('clicked', function () {win.close();});
win.showAll();
Gtk.main();
shell_command("wmctrl -lG");
function shell_command(cmd_str) {
const execSync = require('child_process').execSync;
code = execSync(cmd_str);
return code.toString();
}
在我的 Linux Mint 19.3 系统上,上面的代码创建了一个带有 1 个按钮的小窗口。单击该按钮会导致执行崩溃,并出现以下终端错误:
Error: Command failed: wmctrl -lG
X Error of failed request: BadWindow (invalid Window parameter)
Major opcode of failed request: 20 (X_GetProperty)
Resource id in failed request: 0x6c00003
Serial number of failed request: 26
Current serial number in output stream: 26
window id0x6c00003是上面代码创建的窗口的window id,在运行脚本之后,按下按钮之前运行wmctrl可以证明。
如果我只是将wmctrl 的调用放在一个 50 毫秒的计时器中,它就可以正常工作。
setTimeout(function () {shell_command("wmctrl -lG");}, 50);
这就是让我相信这是一种竞争条件的原因。我认为wmctrl 在我的窗口仍然存在时正在获取窗口 id,但是在我的窗口关闭之后 进一步查询这些 id,这会导致上述错误。这是我的理论,如果它是正确的,Gtk.main() 在窗口真正消失之前返回(并且提到的其他事件也是如此)。
【问题讨论】:
-
一般来说,这些信号delete-event、destroy和destroy-event起作用。您能否分享一个示例代码,也许我们可以理解它为什么不起作用。
-
并不是它们根本不工作,而是它们工作时窗口还在屏幕上。
destroy-event似乎实际上不起作用,但这可能与在创建时启用它的需要有关,我没有这样做,也不知道该怎么做。共享代码很困难,因为这是更广泛的应用程序的一部分,而且因为我使用的是大多数人不熟悉的节点模块。不过,我会尝试编辑一些内容。 -
@SivaGuru 代码已添加。
-
收到销毁信号后,尝试调用一个释放所有对主窗口的引用的函数(gtk_widget_destroy 或 g_object_unref 或),然后尝试调用 Gtk.mainQuit()。我尝试修改 c 代码,但它在那里工作。您将其称为响应条件的理由似乎是有效的(此问题也可能与 node-gtk 有关)。