退出前加倍 Gtk::Messadialog

double Gtk::Messadialog before quitting

如果 运行 程序的 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 有效,它会按预期显示消息对话框,但如果我点击 "yes"(退出应用程序),它会显示另一个消息对话框..为什么?

你说FormUI是从Gtk::Window派生出来的。 Gtk::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() 是虚拟的,因此两次连接都采用您自己的方法。

好的,为什么我们仍然得到两个对话框? returning false不是关闭window吗?不是真的。

delete-event 是一个 GDK 事件。 GDK事件总是return一个布尔值:如果值为falseGDK_EVENT_PROPAGATE),信号连接链中的下一个信号处理程序是运行,如果return 值为 true (GDK_EVENT_STOP),信号连接链中没有进一步的信号为 运行.

碰巧如果你不阻止 delete-event 通过信号连接链传播,window 就会被破坏。因此,当只有一个处理程序连接时,从该处理程序 returning false有效地 破坏 window.

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

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