删除 GTK+ 容器子项,重新填充它,然后刷新
Posted
技术标签:
【中文标题】删除 GTK+ 容器子项,重新填充它,然后刷新【英文标题】:Remove GTK+ container children, repopulate it, then refresh 【发布时间】:2012-02-29 19:45:45 【问题描述】:我遇到了 GTK+ C 应用程序的问题。我有一个容器,在启动应用程序时,它包含一个按钮。在运行期间,用户交互必须使此小部件包含更多。 我需要编写一个函数来删除所有“旧”内部按钮,然后从列表中添加所有按钮,最后刷新视图。这就是我正在写的内容,但缺少某些部分(TODO)
void refresh_sequence_panel()
GSList* iterator = NULL;
GtkWidget* button;
// TODO: Here the container must be empty
// Now add all the buttons
for (iterator = steps; iterator; iterator = iterator->next)
button = gtk_button_new_from_stock(GTK_STOCK_ADD);
gtk_widget_set_size_request(button, SEQ_BUTTON_W, SEQ_BUTTON_H);
gtk_box_pack_start(GTK_BOX(sequence_panel), button, FALSE, FALSE, 5);
handler_id = g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(seq_popup), GTK_BOX(sequence_panel));
// TODO: Now refresh the view, so I can see the changes...
希望有人能帮忙,谢谢!
【问题讨论】:
【参考方案1】:单线:
gtk_container_foreach (GTK_CONTAINER (container), (void*) gtk_widget_destroy, NULL);
【讨论】:
【参考方案2】:这个对我有用(这是 unwind 答案的变体):
Glib::ListHandle<Widget*> childList = this->get_children();
Glib::ListHandle<Widget*>::iterator it = childList.begin();
while (it != childList.end())
remove(*(*it));
it++;
(GTKMM 2.4)
【讨论】:
对于Gtk::manage()
d 小部件有一个主要警告:Container.remove()
在这些小部件上不会 破坏小部件,假设它是一个典型的小部件,最初具有来自的浮动引用C库。相反,gtkmm
恢复浮动引用。因此,如果您 manage()
一个小部件并稍后将其从其父级中删除,它会通过浮动引用保持活动状态。这意味着,如果您希望像在 GTK+ 中那样删除 delete
/free 小部件,那么您就错了,并可能导致大量内存泄漏。所以,你必须remove()
和delete
,但既然delete
将remove()
,你应该只是delete
【参考方案3】:
这是我遵循的方法。因为我在 c++ 上使用 gtkmm
Gtk::Box_Helpers::BoxList *childList = &vboxImgLst->children();
Box_Helpers::BoxList::iterator start = childList->begin();
Box_Helpers::BoxList::iterator end = childList->end();
childList->erase(start, end);
vboxImgLst在哪里,
VBox *vboxImgLst;
希望这对正在使用 gtkmm 和 c++ 的人有所帮助。
谢谢
【讨论】:
谢天谢地,这个丑陋的附加 API 在gtkmm
3 中被删除了,因为它看起来非常不直观,至少从 Container.get_children()
的 PoV 来看,它(必然)返回非拥有指针。【参考方案4】:
删除所有子项:
GList *children, *iter;
children = gtk_container_get_children(GTK_CONTAINER(container));
for(iter = children; iter != NULL; iter = g_list_next(iter))
gtk_widget_destroy(GTK_WIDGET(iter->data));
g_list_free(children);
请注意,上面只是直接删除每个子小部件,而不是要求容器将其删除(使用gtk_container_remove()
),这是recommended by the documentation 并且符合您的意图,所以我认为这很好。
只要您实际将新构建的小部件添加并显示到容器中,“刷新视图”就没有任何意义。 GTK+ 是基于事件的,向容器中添加子元素可以使容器意识到它需要自动刷新其视觉外观。
【讨论】:
谢谢,我确定它需要刷新。 你也可以这样做:gtk_container_foreach (GTK_CONTAINER (container), (GtkCallback) gtk_widget_destroy, NULL)以上是关于删除 GTK+ 容器子项,重新填充它,然后刷新的主要内容,如果未能解决你的问题,请参考以下文章
通过核心数据加载文件后,NSBrowser 不会从 NSTreeController 重新填充子项
如何在kendo树视图中重新加载或刷新整个分支(父级+子级)