当我的Gtk3窗口*已经*关闭时,我可以挂接什么事件?

当我的Gtk3窗口*已经*关闭时,我可以挂接什么事件?,gtk,gdk,Gtk,Gdk,我希望在Gtk3窗口关闭后执行一些代码。我尝试了delete event,destroy,以及destroy event,但似乎根本没有触发 我知道Gdk和Gtk之间有一些区别,但我不确定这到底是什么。我想我问的是对的 我正在使用gtk\u window\u new()的node.js绑定创建窗口,并使用gtk\u window\u close()关闭它。当执行此操作并使用上述事件时,事件处理程序会在窗口仍在屏幕上时启动 编辑: 根据要求,一些示例代码: const gi = require('

我希望在Gtk3窗口关闭后执行一些代码。我尝试了
delete event
destroy
,以及
destroy event
,但似乎根本没有触发

我知道Gdk和Gtk之间有一些区别,但我不确定这到底是什么。我想我问的是对的

我正在使用
gtk\u window\u new()
的node.js绑定创建窗口,并使用
gtk\u window\u 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();

}
在我的LinuxMint19.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
窗口id
0x6c00003
是由上述代码创建的窗口的窗口id,运行脚本后但按下按钮前运行wmctrl可以证明这一点

如果我简单地将对
wmctrl
的调用放在一个50毫秒的计时器中,它就会正常工作

setTimeout(function () {shell_command("wmctrl -lG");}, 50);
这让我相信这是一种比赛状态。我认为
wmctrl
在我的窗口仍然存在时获取窗口ID,但在我的窗口关闭后进一步查询这些ID,从而导致上述错误。这是我的理论,如果它是正确的,
Gtk.main()
在窗口真正消失之前返回(提到的其他事件也是如此)。

\include
gboolean销毁(gpointer窗口、gpointer测试);
无效破坏1(GtkWidget*窗口,gpointer测试);
int main(int argc,char*argv[]){
GtkWidget*窗口;
gtk_init(&argc,&argv);
窗口=gtk_窗口_新建(gtk_窗口_顶层);
gtk_小部件_添加_事件(gtk_小部件(窗口)、GDK_所有_事件_掩码);
gtk_widget_show(窗口);
g_信号连接(窗口,“销毁”,g_回调(销毁1),空);
g_信号连接(窗口,“销毁事件”,g_回调(销毁),空);
gtk_main();
printf(“关闭应用程序”);
//您可以尝试在此处添加代码
//只有在窗口被破坏后才会退出
睡眠(10);
返回0;
}
无效销毁1(GtkWidget*窗口,gpointer测试){
printf(“睡眠5秒\n”);
gtk_小部件_销毁(gtk_小部件(窗口));
睡眠(5);
gtk_main_quit();
printf(“我睡过觉”\n);
}
gboolean销毁(gpointer窗口、gpointer测试){
printf(“睡眠5秒\n”);
睡眠(5);
printf(“我睡过觉”\n);
返回TRUE;
}
当窗口被完全破坏后,主循环将结束。因此,您可以尝试在gtk_main()之后添加代码

当gdk窗口被破坏时,会发出::destroy事件信号。您很少会收到这种信号,因为大多数小部件在销毁窗口之前都会断开自己与窗口的连接,所以在销毁时没有任何小部件拥有窗口。
()。

通常,这些信号删除事件、销毁和销毁事件工作。你能和我们分享一个示例代码吗?也许我们可以理解为什么它不工作。不是它们根本不工作,而是它们工作时窗口仍然在屏幕上<代码>销毁事件似乎实际上不起作用,但这可能与需要在创建时启用它有关,我还没有这样做,也不知道怎么做。共享代码很难,因为这是更广泛应用程序的一部分,而且因为我使用的是大多数人都不熟悉的节点模块。但是,我将尝试在中编辑一些。@SivaGuru代码已添加。在获得销毁信号后,请尝试调用一个函数,该函数释放对主窗口的所有引用(gtk_widget_destroy或g_object_unref or),然后尝试调用gtk.mainQuit()。我试着修改c代码,但它在那里工作。你称之为reace条件的理由似乎是正确的(这个问题也可能与节点gtk有关)。我真不敢相信我是个白痴。显然,把它放在
main()
之后才是应该做的事情。结果证明这并没有起到作用。相反,它导致了
wmctrl
中出现的竞争条件。本质上,发生的是
Gtk.main()
win.close()
之后返回,然后我的代码调用
wmctrl
,在Gtk实际关闭窗口时运行,这会导致
wmctrl
抛出错误
Gtk.main()
没有同步结束。我不理解这个问题。你可以像任何示例工作代码一样用wmctrl更新代码吗..我在原始帖子中进一步更新了代码并扩展了解释。我已经改变了我的应用程序,使它不再重要,但未来的搜索可能会关心。
#include <gtk/gtk.h>

gboolean destroy(gpointer window, gpointer testing);

void destroy1(GtkWidget *window, gpointer testing);

int main(int argc, char *argv[]) {

  GtkWidget *window;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  gtk_widget_add_events(GTK_WIDGET(window), GDK_ALL_EVENTS_MASK);

  gtk_widget_show(window);

  g_signal_connect(window, "destroy", G_CALLBACK(destroy1), NULL);
  g_signal_connect(window, "destroy-event", G_CALLBACK(destroy), NULL);

  gtk_main();

  printf("closing application \n");
  // you could try to add the code here 
  //which will be only be exited after the window is destroyed
  sleep(10);
  return 0;
}

void destroy1(GtkWidget *window, gpointer testing) {
  printf("sleeping for 5 seconds \n");
  gtk_widget_destroy(GTK_WIDGET(window));
  sleep(5);
  gtk_main_quit();
  printf("i have slept \n");
}

gboolean destroy(gpointer window, gpointer testing) {
  printf("sleeping for 5 seconds \n");
  sleep(5);
  printf("i have slept \n");

  return TRUE;
  }