如何在运行时从 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
:
- 如果我告诉
Gtk::Builder::get_widget()
从 .glade
文件中检索根 Gtk::Window
并将其添加为新选项卡,它不会编译,因为我必须传递一个 Gtk::Widget
到 append_page()
并且它不会接受 Gtk::Window
参数。
如果我告诉它选择 top-most 小部件,那么我会收到一堆运行时错误:
Can't set a parent on widget which has a parent
gtkcontainer.c:858: container class `gtkmm__GtkWindow' has no child property named `tab-expand'
gtkcontainer.c:858: container class `gtkmm__GtkWindow' has no child property named `tab-fill'
gtkcontainer.c:858: container class `gtkmm__GtkWindow' has no child property named `tab-label'
gtkcontainer.c:858: container class `gtkmm__GtkWindow' has no child property named `menu-label'
gtkcontainer.c:858: container class `gtkmm__GtkWindow' has no child property named `position'
Gtk:ERROR:gtkcontainer.c:3541:gtk_container_propagate_draw: assertion failed: (gtk_widget_get_parent (child) == GTK_WIDGET (container))
Aborted (core dumped)
如果我使用 top-most 小部件而不是调用 reparent()
并将 Gtk::Notebook
作为新的 parent 传递,那么新选项卡会显示正确排列所有小部件,但我无法控制选项卡的标题。
一定有一个 'correct' 方法可以做到这一点,我只是想不通它是什么!
感谢 gtkmm
邮件列表的帮助,我找到了解决方案。
在 Glade 中,我创建了一个带有单个 Gtk::Box
的 Gtk::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 并为此使用多个对象。
我正在创建一个新的 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
:
- 如果我告诉
Gtk::Builder::get_widget()
从.glade
文件中检索根Gtk::Window
并将其添加为新选项卡,它不会编译,因为我必须传递一个Gtk::Widget
到append_page()
并且它不会接受Gtk::Window
参数。 如果我告诉它选择 top-most 小部件,那么我会收到一堆运行时错误:
Can't set a parent on widget which has a parent gtkcontainer.c:858: container class `gtkmm__GtkWindow' has no child property named `tab-expand' gtkcontainer.c:858: container class `gtkmm__GtkWindow' has no child property named `tab-fill' gtkcontainer.c:858: container class `gtkmm__GtkWindow' has no child property named `tab-label' gtkcontainer.c:858: container class `gtkmm__GtkWindow' has no child property named `menu-label' gtkcontainer.c:858: container class `gtkmm__GtkWindow' has no child property named `position' Gtk:ERROR:gtkcontainer.c:3541:gtk_container_propagate_draw: assertion failed: (gtk_widget_get_parent (child) == GTK_WIDGET (container)) Aborted (core dumped)
如果我使用 top-most 小部件而不是调用
reparent()
并将Gtk::Notebook
作为新的 parent 传递,那么新选项卡会显示正确排列所有小部件,但我无法控制选项卡的标题。
一定有一个 'correct' 方法可以做到这一点,我只是想不通它是什么!
感谢 gtkmm
邮件列表的帮助,我找到了解决方案。
在 Glade 中,我创建了一个带有单个 Gtk::Box
的 Gtk::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 并为此使用多个对象。