This is my code:
void window_first();
void enter_window2(GtkWidget* w, gpointer data);
void quit(GtkWidget* w, gpointer data);
void quit();
int main(int argc, char* argv[])
{
GtkWidget* window2;
gtk_init(&argc, &argv);
window_first();
window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_show_all(window2);
g_signal_connect(G_OBJECT(window2), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return 0;
}
void quit(GtkWidget* w, gpointer data)
{
exit(1);
}
void enter_window2(GtkWidget* w, gpointer data)
{
gtk_main_quit();
}
void window_first()
{
GtkWidget* window1, *vbox, *enter_window2_button;
window1 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
enter_window2_button = gtk_button_new_with_label("enter_window2");
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
gtk_box_pack_start(GTK_BOX(vbox),enter_window2_button, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(window1), vbox);
g_signal_connect(G_OBJECT(window1), "destroy", G_CALLBACK(quit), NULL);
g_signal_connect(G_OBJECT(enter_window2_button), "clicked", G_CALLBACK(enter_window2), NULL);
gtk_widget_show_all(window1);
gtk_main();
return;
}
the purpose of my code is to construct a GtkWindow called "window1" which has a GtkButton called enter_window2 first and construct another GtkWindow called "window2" after the window1 was destroyed. I expect the window1 being destroyed by clicking the "enter_window2" button. However, when I run the code. things goes not as expected. In another word, when I press the button, the window2 is displayed, but the window1 is not destroyed. So how to solve it?
You don't need nested main loops for this, and you shouldn't use them anyway: they are an anti-pattern, and GTK is moving away from even allowing them (GTK 4 is removing gtk_dialog_run()
and might not even let you 'roll your own').
You can and should simply use signals to do this. You just need to get them right. Chiefly: we must disconnect the ::destroy
handler on window1
before we destroy it as part of switching to window2
. Otherwise, it's easy:
#include <gtk/gtk.h>
void window_first();
void enter_window2(GtkWidget* w, gpointer data);
void window_second();
int main(int argc, char* argv[])
{
gtk_init(&argc, &argv);
window_first();
gtk_main();
return 0;
}
void enter_window2(GtkWidget* w, gpointer data)
{
GtkWindow *window1 = GTK_WINDOW(data);
g_signal_handlers_disconnect_by_func(window1, gtk_main_quit, NULL);
gtk_widget_destroy(GTK_WIDGET(window1));
window_second();
}
void window_first()
{
GtkWidget *window1 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget *enter_window2_button = gtk_button_new_with_label("enter_window2");
GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
gtk_box_pack_start(GTK_BOX(vbox),enter_window2_button, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(window1), vbox);
g_signal_connect(window1, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(enter_window2_button, "clicked", G_CALLBACK(enter_window2), window1);
gtk_widget_show_all(window1);
}
void window_second()
{
GtkWidget *window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_show_all(window2);
g_signal_connect(window2, "destroy", G_CALLBACK(gtk_main_quit), NULL);
}
Note that you don't need to cast to GOBject*
for g_signal_connect()
or various other 'functions', which are really macros that check that for you.