Gtk3用另一个小部件替换子小部件

Posted

技术标签:

【中文标题】Gtk3用另一个小部件替换子小部件【英文标题】:Gtk3 replace child widget with another widget 【发布时间】:2014-12-07 13:34:40 【问题描述】:

我正在寻找一种方法来从其父级中删除一个小部件(无论它是什么 - VBox、一个网格等)并在其位置添加一个替代小部件。

我找到了this answer,但我似乎无法让它与 Gtk3 一起使用。

这是我尝试过的:

from gi.repository import Gtk

def replace_widget(old, new):
    parent= old.get_parent()

    props= 
    for key in Gtk.ContainerClass.list_child_properties(type(parent)):
        props[key.name]= parent.child_get_property(old, key.name)

    parent.remove(old)
    parent.add_with_properties(new, **props)

但是对Gtk.ContainerClass.list_child_properties 的调用引发了

TypeError: argument self: Expected a Gtk.ContainerClass, but got gi.repository.Gtk.GObjectMeta

它也不接受容器小部件的实例。对于我的生活,我无法弄清楚我应该传递什么参数。

P.S.:我知道我可以在容器和子小部件之间添加另一个小部件,但我不想这样做。

更新:我想这还不够清楚:替代小部件应该与原始小部件位于同一位置,具有相同的打包属性。

【问题讨论】:

这是一个如何使用树视图的示例:***.com/questions/27747172/… 【参考方案1】:

这直到最近才成为可能,因为 PyGObject 3.14:https://git.gnome.org/browse/pygobject/commit/?h=pygobject-3-14&id=bf84915f89fd5fd502b4fb162eef7bc0a48c8783

以下任何一项都适用于 PyGObject 3.14 及更高版本:

parent.list_child_properties()
Gtk.ContainerClass.list_child_properties(parent)

(第二种语法是在类和实例方法有命名冲突的情况下。见讨论here。)

【讨论】:

我已经发布了工作代码as an answer,但如果您愿意,我们可以将其添加到您的答案中? 感谢您的回答,我认为将其作为单独的答案很好。如果您愿意合并它们,也可以随时编辑我的答案!【参考方案2】:

感谢ptomato's answer提供的信息,下面是工作代码:

def replace_widget(old, new):
    parent = old.get_parent()

    props = 
    for key in Gtk.ContainerClass.list_child_properties(type(parent)):
        props[key.name] = parent.child_get_property(old, key.name)

    parent.remove(old)
    parent.add(new)

    for name, value in props.iteritems():
        parent.child_set_property(new, name, value)

【讨论】:

【参考方案3】:

我知道它是如何与 C 一起工作的,我没有用 python 尝试过:

 parent = gtk_widget_get_parent(old);
 g_object_ref(_key); /** because gtk_container_remove remove the widget with its reference we have to increment the number of reference if we want to reuse the old widget **/
 gtk_container_remove(GTK_CONTAINER(parent), old);
 gtk_container_add(GTK_CONTAINER(parent), new);

PS : 在 VBox 或 Grid 的情况下,小部件没有插入旧的位置,您必须指定插入位置(旧的位置)

祝你好运,

【讨论】:

【参考方案4】:

你可以试试 Gtk.Widget 的reparent() 方法。您可以在此gtkwidget/reparent link in archive.org 查看文档。如果我没记错的话,您应该首先重新设置子小部件,然后删除旧的父小部件。如果它在评论中不起作用,我会检查我的文档(目前不在该机器上)。

【讨论】:

请不要只在此处发布链接。请复制您引用的方法。 对不起,我有点困惑。如果不需要,为什么允许链接?方法名是reparent() 链接用于获取更多信息。您应该执行以下操作:尝试此方法:reparent() 请参阅此链接以获取更多信息。 @JSK NS 我很抱歉。感谢您的建议。我会编辑帖子,这个 cmets 可以删除。 这不会在旧小部件的位置添加新小部件。这与 YouzKing 建议的基本相同。

以上是关于Gtk3用另一个小部件替换子小部件的主要内容,如果未能解决你的问题,请参考以下文章

在子小部件中,如何在 kivy 中获取父小部件的实例

是否可以强制对齐 Wrap 小部件中的特定子小部件?

如何从 Flutter 中的子小部件调用父小部件功能

如何将父小部件焦点重定向到子小部件?

Kivy 如何访问子小部件中的小部件

Qt半透明背景导致子小部件在父小部件中“印记”