我想在删除窗口时更改到笔记本中的某个页面,并在有效删除窗口之前做一些工作。下面的代码为get_current_page提供了1,但该页面并没有有效地更改为1。
这个问题的解决方案应该是什么?
Form::Form()
{
add(box);
notebook.set_size_request(800, 600);
notebook.set_show_tabs(false);
box.pack_start(notebook, Gtk::PACK_SHRINK);
label_intro.set_text("Intro");
box_intro.pack_start(label_intro);
box_intro.show();
label_exit.set_text("Preparing clean exit ... Please wait!");
box_exit.pack_start(label_exit);
box_exit.show();
notebook.insert_page(box_intro, "Intro", 0);
notebook.insert_page(box_exit, "Exit", 1);
signal_delete_event().connect(sigc::mem_fun(*this, &Form::is_deleted));
set_title("title");
resize(800, 600);
show_all();
}
bool Form::is_deleted(GdkEventAny *any_event)
{
notebook.set_current_page(1);
std::cout << "current_page " << notebook.get_current_page() << std::endl; // gives 1
std::this_thread::sleep_for(2000ms);
return Window::on_delete_event(any_event);
}
class Form : public Window
{
public:
Form();
private:
bool is_deleted(GdkEventAny *any_event);
private:
// Form
Box box;
Notebook notebook;
Box box_intro, box_exit;
Label label_intro, label_exit;
};
很抱歉回答得太晚了,你的问题让我的工作比我想象的要忙!
使用Glib::TimeoutSource
类(它被荒谬地低估了…(,我能够绕过这个限制。
基本上,我的策略是,只需单击一下,就可以运行两次delete-event
信号处理程序:
- 一次以更新笔记本。在这种情况下,我们返回CCD_;完全处理";信号和传播不应该发生,因此不会关闭窗口。此时,用户看到了UI中的更改,但尚未完成任何工作。在这个过程中,我们还设置了一个
Glib::Timeout
,以便稍后在窗口上调用close
方法,再次调用delete-event
信号处理程序 - 两次做这项工作。这一次,我们做了真正的工作(UI已经更新(。工作完成后,我们传播处理程序并关闭窗口
这是这个代码*:
#include <chrono>
#include <iostream>
#include <thread>
#include <gtkmm.h>
using namespace std::chrono_literals;
class Form : public Gtk::Window
{
public:
Form();
private:
Gtk::Box box;
Gtk::Notebook notebook;
Gtk::Box box_intro;
Gtk::Box box_exit;
Gtk::Label label_intro;
Gtk::Label label_exit;
// This flag indicates if a first call to the "delete-event" signal
// has been done. On a second call to this event, this should be
// set to "true" to alter the handler's behaviour.
bool flag = false;
};
Form::Form()
{
add(box);
notebook.set_size_request(800, 600);
notebook.set_show_tabs(false);
box.pack_start(notebook, Gtk::PACK_SHRINK);
label_intro.set_text("Intro");
box_intro.pack_start(label_intro);
box_intro.show();
label_exit.set_text("Preparing clean exit ... Please wait!");
box_exit.pack_start(label_exit);
box_exit.show();
notebook.insert_page(box_intro, "Intro", 0);
notebook.insert_page(box_exit, "Exit", 1);
signal_delete_event().connect(
[this](GdkEventAny *any_event)
{
if(!flag)
{
// First time in. We change the notebook page:
notebook.set_current_page(1);
// If we block right away and don't return from
// this handler, the GUI will freeze. Hence, we set
// a timer to "close" the window in 10ms. Not that
// closing the window will call once more this handler...
Glib::signal_timeout().connect(
[this]()
{
close();
return false; // Disconnect after on call...
},
10
);
// So we change the flag value, to alter its behavior on the
// next pass.
flag = true;
return true; // Fully handled for now... leaving the handler.
// This will allow the main loop to be run and the
// window to uptate.
}
// On the second run, we do the work:
std::this_thread::sleep_for(1900ms);
// And we close the window (for real this time):
return Window::on_delete_event(any_event);
}
);
set_title("title");
resize(800, 600);
show_all();
}
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
Form window;
window.show_all();
return app->run(window);
}
*我随意使用lambda表达式,因为我认为它们更可读、更封装,我不确定你是否知道它们。无论如何,采取感觉最好的方式
我知道这是一种黑客攻击,但在尝试了很多之后,我开始相信这是我们在不处理更多涉及的多线程策略的情况下所能达到的最佳效果(遗憾的是,我不是这方面的专家(。
希望这至少能暂时解决你的问题。