退出前加倍 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::Window
有 a 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一个布尔值:如果值为false
(GDK_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
中的输入),您将需要知道这一点。
如果 运行 程序的 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::Window
有 a 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一个布尔值:如果值为false
(GDK_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
中的输入),您将需要知道这一点。