C GTK 在通过 ESC 关闭后无法再次打开对话框

C GTK can't open Dialog again after closing via ESC

我有一个名为 dlg_open 的对话框,带有一个 btn_cancel_open 按钮。 此对话框在 Buton-Event 和对话框的 close 事件映射到:

void on_btn_cancel_clicked (GtkWidget *widget, signal_map_data *smd) {
  #ifdef debug
    g_print ("-> on_btn_cancel_clicked\n");
  #endif
  gtk_widget_hide (gtk_widget_get_toplevel (widget) );
  gtk_widget_set_sensitive (smd->widg.wmw.wnd, 1);
}

void on_dlg_close (GtkWidget *widget, signal_map_data *smd) {
  #ifdef debug
    g_print ("-> on_dlg_close\n");
  #endif
  gtk_widget_hide (widget);
  gtk_widget_set_sensitive (smd->widg.wmw.wnd, 1);
}

这很好用。这是我打开对话框的方式:

void on_btn_open_clicked (GtkWidget *widget, signal_map_data *smd) {
  #ifdef debug
    g_print ("-> on_btn_open_clicked\n");
  #endif
  gtk_widget_set_sensitive (smd->widg.wmw.wnd, 0);
  gtk_widget_show (smd->widg.wdow.dlg_open);
}

我的问题是,当我通过按键 ESC 关闭对话框时,我无法再次打开它,主 window 丢失了它的 sensitivity,但是对话框没有' 出现,并且在控制台打印出一条错误消息:

Gtk-CRITICAL **: gtk_widget_show: assertion 'GTK_IS_WIDGET (widget)' failed

当我通过 cancel-button 关闭对话框时,它工作正常,我可以重新打开对话框 window。

只是 ESC 的问题。

但是where/why?

根据 andlabs 进行编辑 答案:(!!已更新!!)

我从on_dlg_close功能改成了response管理功能:

void on_dlg_response (GtkDialog *dlg, gint r_id, signal_map_data *smd) {
  #ifdef debug
    g_print ("-> on_dlg_response\n");
  #endif
  switch (r_id) {
    case GTK_RESPONSE_DELETE_EVENT: {
      gtk_widget_hide (dlg);
      gtk_widget_set_sensitive (smd->widg.wmw.wnd, 1);
    }
  }
}

我还添加了 delete-event:

gboolean on_dlg_delete (GtkWidget *widget, GdkEvent *event, signal_map_data *smd) {
  #ifdef debug
    g_print ("-> on_dlg_delete\n");
  #endif
  return FALSE;
}

这也适用于使用 ESC 关闭对话框。但是仍然存在同样的问题,当我通过 ESC 按钮关闭对话框时无法重新打开对话框,出现相同的错误:

-> on_dlg_response

-> on_dlg_delete

-> on_btn_add_clicked

(main:16478): GLib-GObject-WARNING **: invalid unclassed pointer in cast to 'GtkLabel'

(main:16478): Gtk-CRITICAL **: gtk_label_set_text: assertion 'GTK_IS_LABEL (label)' failed

(main:16478): Gtk-CRITICAL **: gtk_widget_show: assertion 'GTK_IS_WIDGET (widget)' failed

如何解决这个问题?

您不想连接到 close;对于按下的 Escape 键,那是 。相反,连接到 response 并检查已知响应。

一个 GtkDialog 就是一个 GtkWindow;默认情况下,当您单击关闭按钮时,它会被销毁。您将需要连接到 delete-event 以规避此行为。 (gtk_dialog_run() 为您完成此操作,这就是为什么单击具有该功能的对话框 运行 上的关闭按钮而不是手动不会破坏小部件的原因。当然,覆盖仅在持续时间内生效电话。)

当然,这意味着您需要特殊处理才能在别处关闭对话框。 GtkDialog 安装它自己的信号处理程序,在继续删除之前发出 responseGTK_RESPONSE_DELETE_EVENT。如果您只使用 g_signal_connect(),您的代码将在 运行 之前有机会 运行,并且您需要在两个地方设置对话框关闭逻辑。我不知道您是否可以使用 g_signal_connect_after() 将自己置于 GtkDialog 的处理程序和默认处理程序之间,但值得一试。如果这确实有效,那么您的 delete-event 可能只是一个 return TRUE;,而您在 response 中进行所有响应处理。