我正在编写一个gtkmm3应用程序,我需要从非GUI线程创建和显示新的GUI元素。具体来说,我正在尝试将标签添加到笔记本中。
我在gui线程中创建笔记本,如下所示:
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
if(!Glib::thread_supported()) Glib::thread_init();
Gtk::Window window;
notebook = new Gtk::Notebook();
window.add(*notebook);
notebook -> show();
Worker bee;
bee.start();
return app->run(window);
我创建并添加了一个新选项卡,如下所示:
Gtk::Label label("label");
Gtk::Label child("child");
notebook -> append_page(child, label);
notebook -> show_all();
如果我在notebook->show()
之前插入标签创建代码,它可以正常工作。但是,如果我将制表符创建代码放入其自己的工作线程中,则新选项卡永远不会显示。
我猜测失败与在工作线程上创建新选项卡并且违反GUI线程约定中gtkmm的GUI内容这一事实有关。
问题是工作线程负责创建新选项卡,而且我不知道在编译时要创建多少个选项卡。
在像Swing和gtk +这样的API中,有处理这种情况的机制。在Swing中有一个invokeLater方法,它允许我将一个lambda传递给GUI线程进行调用,gtk +使用gdk_threads_enter / leave来确保只有一个线程一次播放GUI。
gtkmm对这个问题的回答是什么?
答案 0 :(得分:0)
一般来说,除了主线程之外,你应该避免使用GTK +(或gtkmm)UI API。这并不意味着工作。
当另一个线程说它应该时,你需要让主线程响应,而不是在另一个线程中实际执行UI工作。人们喜欢使用Glib :: Dispatcher与gtkmm:https://developer.gnome.org/gtkmm-tutorial/stable/sec-using-glib-dispatcher.html.en。
但是也要认真考虑是否真的需要另一个线程。在空闲处理程序中完成工作可能没什么问题:https://developer.gnome.org/gtkmm-tutorial/stable/sec-idle-functions.html.en