Подтвердить что ты не робот

Gtk3 заменит дочерний виджет другим виджетами

Я ищу способ удалить виджет из его родителя (независимо от того, что может быть - VBox, Grid,...) и добавить вместо него замещающий виджет.

Я нашел этот ответ, но я не могу заставить его работать с 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.: Я знаю, что я мог добавить еще один виджет между контейнером и дочерним виджетами, но я бы предпочел не делать этого.

ОБНОВЛЕНИЕ: Я предполагаю, что это было недостаточно ясно: замещающий виджет должен находиться в том же месте, что и исходный виджет, с теми же свойствами упаковки.


Благодаря ptomato, здесь рабочий код:

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)
4b9b3361

Ответ 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)

(Второй синтаксис в том случае, если методы класса и экземпляра имеют конфликт имен. См. обсуждение здесь.)

Ответ 2

Я знаю, как это работает с 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 виджет не вставлен в место старого, вы должны указать положение вставки (позиция старого whild)

удачи,

Ответ 3

Вы можете попробовать reparent() метод Gtk.Widget. Вы можете проверить документы на этой ссылке. Если я хорошо помню, вы должны сначала увидеть дочерний виджет, а затем удалить старый родительский виджет. Если он не работает в комментарии, и я проверю свои документы (в настоящее время не на этой машине).