如何在运行时从 Glade 定义中添加 Gtk::Notebook 选项卡?

How do you add Gtk::Notebook tabs at runtime from Glade definitions?

我正在创建一个新的 GTK 应用程序(使用 gtkmm),主界面是选项卡式的,有点像网络浏览器。

我想为用户打开的每个文档创建一个新选项卡,每个选项卡的内容由 Glade 定义。我是 gtkmm 的新手,所以我不知道该怎么做。

如果我在 Glade 中将选项卡设计为 self-contained window,当我调用 Gtk::Builder::get_widget() 时,它 returns 指向 Gtk::Window 的指针,但是我无法将其传递给 Gtk::Notebook::append_page(),因为该函数需要一个引用,而我只有一个指针。我不想取消引用指针,因为我相信每次调用 get_widget() returns 相同的指针 - 所以如果我想添加相同的五个页面,我需要以某种方式克隆 UI 结构,然后再将它添加到 Gtk::Notebook - 否则更改一个选项卡上的 UI 元素将导致它在其他四个选项卡上也发生变化,因为它们都指向相同的 UI小部件。

将在 Glade 中设计的 window 动态添加到 Gtk::Notebook 中的最佳方法是什么?


编辑:

将每个选项卡的定义放入一个单独的 *.glade 文件中确实允许我加载多个实例,所以这部分都很好。

但是我仍然无法将加载的结构添加到 Gtk::Notebook:

一定有一个 'correct' 方法可以做到这一点,我只是想不通它是什么!

感谢 gtkmm 邮件列表的帮助,我找到了解决方案。

在 Glade 中,我创建了一个带有单个 Gtk::BoxGtk::Window,并将我所有的控件放在 Box 中。这在尝试将 Box 添加为新选项卡时导致问题,因为 Box 已经有一个 parent(Gtk::Window),因此尝试制作 Gtk::Notebook新的parent.

相反,我发现您可以在 Glade 中 Gtk::Box 的按钮上 right-click,然后选择 "Add widget as toplevel"。然后根本不需要 Gtk::Window,并且由于 Box 没有 parent,调用 Gtk::Notebook::append_page() 并传递 Gtk::Box 可以完美地工作。然后我可以使用 append_page() 的变体,让我同时设置选项卡的标题。

但是仍然需要创建一个新的 Gtk::Builder 实例来为每个选项卡加载控件,因为每个选项卡都需要一个新的控件实例。如果您只是在同一个 object 上继续调用 Gtk::Builder::get_widget(),它 returns 控件的同一个实例。

一般来说,您应该首先在 Glade 中完成 GUI 的布局,完成 Window、Notebook and/or 其他嵌套小部件。如果你想要不同的选项卡,那么你也可以在 Glade 中制作它们,但是作为不嵌套在你的顶层中的单独对象 Window。保存 .xml 文件并将其加载到您的程序中。

将您的小部件声明为指针,用 nullptr 初始化并使用类似这样的东西来访问您在 Glade 中创建的小部件:

 m_refBuilder->get_widget("my_tabbox00", m_pTab00);

现在您可以使用(Glade id)my_tabbox00 作为(C++)指针 m_pTab00。只需确保 my_tabbox00 在 Glade 中没有父项,它可以包含子项。您还可以对笔记本和视口使用 get_widget()(即使小部件有父级)。要附加页面,您可以使用:

m_pNotebook->append_page(*m_pViewport00, *m_pTab00);

请注意,此解决方案对您有一点限制,因为对于每个选项卡,您都必须在 Glade 中创建一个新选项卡和视口。也许更好的方法是尝试为选项卡制作 class 并为此使用多个对象。