删除 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,但既然deleteremove(),你应该只是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+ 容器子项,重新填充它,然后刷新的主要内容,如果未能解决你的问题,请参考以下文章

瓦拉。如何删除 GTK 容器的所有子项?

通过核心数据加载文件后,NSBrowser 不会从 NSTreeController 重新填充子项

如何在kendo树视图中重新加载或刷新整个分支(父级+子级)

YDN-DB - 删除数据库,然后在页面加载/重新加载时重新创建和加载,但在刷新时不加载

按下按钮后在 React 中重新填充/刷新表

JTable 不会在将数据插入 mysql 时重新绘制/刷新