在退出前双Gtk :: Messadialog

时间:2015-02-24 00:27:13

标签: c++ gtk gtkmm

如果正在运行的程序的pid有效,我正在尝试显示一个消息对话框,这是我的基本代码:

Gtk::Main kit (argc, argv);
Glib::RefPtr<Gtk::Builder> refBuilder = Gtk::Builder::create();
try { refBuilder->add_from_file (UI_PATH); }
catch (const Glib::FileError& ex) {
    std::cout << "FileError: " << ex.what() << std::endl;
    return 1;
}
catch (const Gtk::BuilderError& ex) {
    std::cout << "BuilderError: " << ex.what() << std::endl;
    return 1;
}
FormUI * ui = 0;
refBuilder->get_widget_derived ("window1", ui);
if (ui) {
    kit.run (*ui);
}
delete ui;

构造

signal_delete_event ().connect (sigc::mem_fun (*this, &FormUI::on_delete_event));

方法:

    bool FormUI::on_delete_event (GdkEventAny* event) {
if (_pid) {
    bool retState;
    Gtk::MessageDialog md(*this, Glib::ustring::compose ("<b>%1</b>", _("Warning: youtube-dl in process")), true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
    md.set_title (PACKAGE_STRING);
    md.set_secondary_text (_("Closing can generate a corrupted file, do you want to continue anyway?"));
    if (md.run() == Gtk::RESPONSE_YES) {
        kill (_pid, 0);
        retState = false;
    } else {
        retState = true;
    }
    md.hide ();
    return retState;
}
return false;

}

有了上述内容,如果pid有效,它会按预期显示messagedialog,但是如果我点击“是”(退出应用程序),它会显示另一个messagedialog ..为什么?

1 个答案:

答案 0 :(得分:2)

您说FormUI来自Gtk::WindowGtk::Windowa virtual method on_delete_event()自动连接到delete-event信号,无问题。哎呀,你实现了一个虚拟的方法而不知道它!所以你通过调用

做了什么
signal_delete_event ().connect (sigc::mem_fun (*this, &FormUI::on_delete_event));

在不知不觉中将该信号连接两次,并且因为Gtk::Window::on_delete_event()是虚拟的,所以两个连接都转到您自己的方法。

好的,为什么我们仍然会得到两个对话框?不返回false意味着关闭窗口?不是真的。

delete-event是GDK事件。 GDK事件总是返回一个布尔值:如果值为falseGDK_EVENT_PROPAGATE),则运行信号连接链中的下一个信号处理程序,如果返回值为true({ {1}}),信号连接链中没有其他信号运行。

恰巧如果你没有阻止GDK_EVENT_STOP传播通过信号连接链,窗口就会被破坏。因此,当只连接一个处理程序时,从该处理程序返回delete-event有效地销毁窗口。

但现在你连接了两个处理程序。第一个将返回false,这将导致第二个运行,然后您将获得第二个消息对话框。当那个人返回false时,你的窗户就会被摧毁。

希望这可以解释这个问题。您可以通过不调用false或将方法名称更改为其他内容来解决此问题。请务必观看gtkmm文档,以确保您不会意外使用自动连接到信号的其他虚拟方法(我不确定为什么gtkmm提供这些虚拟方法;方便吗?)。并且一定要了解GDK活动的工作原理;如果您真的使用GDK事件(例如处理signal_delete_event().connect()中的输入),您将需要知道这一点。