旧窗口的信号处理程序被新的窗口信号处理程序取代GTK +
我的GUI应用程序有2个窗口。 主窗口销毁信号设置为使用gtk_main_quit
退出应用程序。旧窗口的信号处理程序被新的窗口信号处理程序取代GTK +
其他窗口销毁信号设置为使用方法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服务器上运行应用程序。
从主窗口启动其他窗口是非常普遍的事情,我想我缺少一些基本的东西。任何可以帮助这里的东西。
还有一个问题可以回答我自己。 这里首先要注意的是为什么我使用@jku指出的两个主循环。 我使用了两个主循环,因为之前只有一个循环,我的进程正在倾卸核心,而我并没有集中检查哪里出了问题,而是开始以其他方式思考并插入一个不需要的主循环。
现在为什么它是倾销核心刚刚击中我的脑海,因为我在我的帖子上写评论。这是被释放的对象,其引用我仍在使用OtherWindow的Button的信号处理程序。 当我在堆栈上创建对象时,一旦函数结束,对象被删除,但后来在信号处理程序中,当我尝试使用它时,它肯定会转储我刚刚知道的核心。
因此,我通过引入一个主循环来处理seg fault的方式是一个非常糟糕的主意,因为我们应该只使用一个主循环,因为引入更多主循环会导致进一步的其他问题,如后面所述。
因此,只有在上面的代码一些变化使得一切权利:
首先要从OtherWindow构造GTK的主循环。
其次动态创建OtherWindow对象如下:
void MainWindow::open_other_window(GtkWidget *widget, gpointer data)
{
OtherWindow* other = new OtherWindow(10);
}
为什么你运行多个mainloops? – jku
我们不必为每个顶层窗口运行主循环。 无论如何,如果你不运行OtherWindow主循环,它会转储核心(分段错误),正如我在文章中提到的那样。 它转储核心的原因是因为一旦OtherWindow被实例化,它会立即被删除,因为在它们之间没有阻塞函数,并且在稍后的信号处理程序中,我们尝试使用对象引用,因为对象已被释放。 – mSatyam
早些时候我确实只使用了一个主循环,但是因为我正在写这个注释而被抛弃了,所以我非常肯定我找到了解决方案。对于某些问题,当我提出一个问题时,只有我的思维才起作用,现在看到我发现什么地方出了问题。让我试着回头确认一下。 感谢让我的大脑足够努力。 – mSatyam