Есть ли хороший способ скопировать виджет Gtk? - PullRequest
7 голосов
/ 09 июня 2010

Есть ли способ, используя библиотеку Gtk в C, клонировать кнопку Gtk (например) и упаковать ее где-нибудь еще в приложении. Я знаю, что вы не можете упаковать один и тот же виджет дважды. И этот код, очевидно, не будет работать, но показывает, что происходит, когда я пытаюсь сделать мелкую копию кнопки:

GtkButton *a = g_object_new(GTK_TYPE_BUTTON, "label", "o_0", NULL);
GtkButton *b = g_memdup(a, sizeof *a);
gtk_box_pack_start_defaults(GTK_BOX(vbox), GTK_WIDGET(b));

Существует окружающий код, который создает vbox, упаковывает его в окно и запускает gtk_main (). Это приведет к сложным для понимания сообщениям об ошибках:

(main:6044): Gtk-CRITICAL **: gtk_widget_hide: assertion `GTK_IS_WIDGET (widget)' failed

(main:6044): Gtk-CRITICAL **: gtk_widget_realize: assertion `GTK_WIDGET_ANCHORED (widget) || GTK_IS_INVISIBLE (widget)' failed
**
Gtk:ERROR:/build/buildd/gtk+2.0-2.18.3/gtk/gtkwidget.c:8431:gtk_widget_real_map: assertion failed: (GTK_WIDGET_REALIZED (widget))

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

Я бы хотел сделать это:

GtkButton *b = copyable_copy(COPYABLE(a));

Если GtkButton может использовать теоретически копируемый интерфейс.

Ответы [ 2 ]

4 голосов
/ 09 июня 2010

Я так не думаю. Насколько я знаю, нет никакой гарантии, что виджеты сохранят все свое состояние в свойствах, к которым вы можете получить доступ извне. Если виджет «скрывает» состояние, не экспортируя его, вы не сможете скопировать его извне.

Технически, виджеты могут просто включать в свое ядро ​​поля struct, которые вы не видите извне реализации, поэтому вы даже не можете копировать биты, используя немой memcpy(), если вы не готовы укажите количество байтов, считая вручную и используя литерал.

При этом вполне возможно, что достаточное количество виджетов предоставляет достаточное состояние через свойства, чтобы копия все еще функционировала и, возможно, демонстрировала лишь незначительные сбои. Это было бы круто. Я бы порекомендовал обратиться напрямую к основным разработчикам GTK +, возможно, в список рассылки gtk-devel-list .

3 голосов
/ 13 июня 2010

Свойства клонирования через это жизнеспособное решение:

GObject *
g_object_clone(GObject *src)
{
    GObject *dst;
    GParameter *params;
    GParamSpec **specs;
    guint n, n_specs, n_params;

    specs = g_object_class_list_properties(G_OBJECT_GET_CLASS(src), &n_specs);
    params = g_new0(GParameter, n_specs);
    n_params = 0;

    for (n = 0; n < n_specs; ++n)
        if (strcmp(specs[n]->name, "parent") &&
            (specs[n]->flags & G_PARAM_READWRITE) == G_PARAM_READWRITE) {
            params[n_params].name = g_intern_string(specs[n]->name);
            g_value_init(&params[n_params].value, specs[n]->value_type);
            g_object_get_property(src, specs[n]->name, &params[n_params].value);
            ++ n_params;
        }

    dst = g_object_newv(G_TYPE_FROM_INSTANCE(src), n_params, params);
    g_free(specs);
    g_free(params);

    return dst;
}

Клонирование виджета не так уж и тривиально, но в большинстве случаев вышеупомянутый подход пригоден (на GtkButton наверняка).1005 *

Мне было бы все равно, что большая часть состояний не представлена ​​свойствами (все надлежащие виджеты должны быть полностью определены свойствами, чтобы их можно было использовать с GtkBuilder), но многие угловые случаи затруднят надежное клонирование (интерфейсы и контейнеры, которые приходят мне в голову первыми).

...