gtkmm&x27;s对gdk_threads_enter()或SwingUtilities.invokeLater()的回答

gtkmm&x27;s对gdk_threads_enter()或SwingUtilities.invokeLater()的回答,swing,gtk,gtkmm,Swing,Gtk,Gtkmm,我正在编写一个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:

我正在编写一个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);
如果我在
notebook->show()
之前插入制表符创建代码,它可以正常工作。但是,如果我将选项卡创建代码放入它自己的工作线程中,新选项卡将永远不会显示

我猜失败与以下事实有关:新选项卡是在工作线程上创建的,并且违反了gtkmm在GUI线程约定上的GUI内容

问题是工作线程负责创建新选项卡,我不知道在编译时要创建多少选项卡

在Swing和gtk+等API中,有一些机制可以处理这种情况。在Swing中有一个invokeLater方法,允许我将lambda传递给GUI线程进行调用,gtk+使用gdk_threads_enter/leave确保一次只有一个线程在玩GUI


gtkmm对此问题的答案是什么?

一般来说,您应该避免从主线程以外的任何地方使用GTK+(或gtkmm)UI API。这不是为了工作

当另一个线程说它应该响应时,您需要让主线程响应,而不是在另一个线程中实际执行UI工作。人们喜欢将Glib::Dispatcher用于gtkmm:


但也要仔细想想你是否真的需要另一个线程。在空闲处理程序中执行这项工作可能没有问题:

gdk\u threads\u enter()
不再是GTK+解决方案
gdk\u threads\u idle\u add()
是新的解决方案;它的工作原理与
SwingUtilities.invokeLater()
完全相同。我不知道gtkmm的等价物是什么,但应该不难找到。。。(甚至是除了C++的特性之外,我不知道为什么你不能仅仅调用GDK函数……)@和Dalab说你可以使用IDLYAdAd或使用Debug(),我不想再要一个线程,我只想我需要一个,因为我从来没有见过这个空闲函数机制。如果我有一个不带参数的简单void函数,那么将它附加到signal\u idle()的语法是什么?如果我有一个简单的函数
void loop()
,将它附加到signal\u idle()的语法是什么?要只调用一次,可以这样做:Glib::signal\u idle().connect\u once(&loop);如果是成员方法,请使用sigc::mem_fun()。要重复调用它,需要使用connect(),并且需要一个返回bool的处理函数。具体做什么取决于函数每次要做多少工作,以及是否需要让主UI了解正在发生的事情。
Gtk::Label label("label");
Gtk::Label child("child");
notebook -> append_page(child, label);
notebook -> show_all();