【发布时间】:2016-11-20 00:51:46
【问题描述】:
我的 GUI 应用程序有 2 个窗口。
主窗口销毁信号设置为使用gtk_main_quit 退出应用程序。
另一个窗口销毁信号被设置为使用方法gtk_widget_destroy销毁该特定窗口。
我们从主窗口启动另一个窗口。当我们点击关闭button(X)启动另一个窗口后,另一个窗口成功销毁但主窗口继续运行,到目前为止一切都很好。
现在,当我们点击主窗口关闭button(X) 时,它并没有退出整个应用程序,而只是破坏了主窗口,进程继续运行。
如果我不从主窗口启动另一个窗口,那么一切正常,应用程序成功退出。
这是重现问题的示例代码:
#include <gtk/gtk.h>
#include <iostream>
using namespace std;
class OtherWindow {
private:
int number;
GtkWidget* window;
GtkWidget* button;
public:
OtherWindow(int num);
static void read_number(GtkWidget *widget, gpointer data);
};
OtherWindow::OtherWindow(int num)
{
number = num;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label("Read Number");
gtk_container_add(GTK_CONTAINER(window), button);
// signal handler
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_widget_destroy), NULL);
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(OtherWindow::read_number), this);
gtk_widget_show_all(window);
gtk_main();
}
void OtherWindow::read_number(GtkWidget *widget, gpointer data)
{
OtherWindow* other_win = static_cast<OtherWindow*>(data);
cout << other_win->number << endl;
}
class MainWindow {
private:
GtkWidget* window;
GtkWidget* button;
public:
MainWindow();
static void open_other_window(GtkWidget *widget, gpointer data);
};
MainWindow::MainWindow()
{
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label("Open Another Window");
gtk_container_add(GTK_CONTAINER(window), button);
// signal handler
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(MainWindow::open_other_window), NULL);
gtk_widget_show_all(window);
gtk_main();
}
void MainWindow::open_other_window(GtkWidget *widget, gpointer data)
{
OtherWindow other(10);
}
int main(int argc, char* argv[])
{
gtk_init(&argc,&argv);
MainWindow win;
}
还有一个疑问是,当我尝试从 OtherWindow 构造函数中删除 gtk_main 循环时,应用程序会成功退出,但是如果我从 OtherWindow 构造函数中删除 gtk_main 循环,然后单击“其他”窗口上的按钮使用指针引用访问成员变量我的应用程序然后得到分段错误。
另外,我没有使用gtkmm,因为我必须在没有编译器支持的旧 Solaris 服务器上运行应用程序,因此我几乎没有限制。
从主窗口启动其他窗口是很常见的事情,我想我缺少一些基本的东西。任何可以在这里提供帮助的东西。
【问题讨论】:
-
为什么要运行多个主循环?
-
我们不必为每个顶层窗口运行主循环。无论如何,如果您不运行 OtherWindow 主循环,它将转储核心(分段错误),正如我在帖子中提到的那样。它转储核心的原因是因为一旦 OtherWindow 被实例化,它就会立即被删除,因为中间没有阻塞函数,然后稍后在其信号处理程序中我们尝试使用对象引用时,它将转储核心,因为对象已经被释放。
-
之前我确实只使用了一个主循环,但在我写这篇评论时它被丢弃了,我很确定我找到了解决方案。对于一些问题,当我提出问题时,只有我的大脑在工作,现在看看我发现了哪里出了问题。让我试着确认一下。感谢您让我的大脑足够努力地思考。!!
-
哦,是的,我找到了
-
感谢@jku 实际上在添加第二个主循环时我感觉这不是正确的做法,但后来我在互联网上找到了一个使用两个主循环的示例,所以我碰巧使用了那时我不知道是什么倾倒了核心。不管怎样,你让我重新思考,这让我现在感觉很轻松。