8

C で Gtk ライブラリを使用して、(たとえば) Gtk ボタンを複製し、アプリの別の場所にパックする方法はありますか。同じウィジェットを 2 回パックできないことはわかっています。そして、このコードは明らかに機能しませんが、ボタンの浅いコピーを試みるとどうなるかを示しています。

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 が理論上のコピー可能なインターフェイスを使用できる場合。

4

2 に答える 2

4

私はそうは思わない。私の知る限り、ウィジェットがすべての状態をプロパティに保持し、外部からアクセスできるという保証はありません。ウィジェットがエクスポートしないことで状態を「非表示」にした場合、外部からコピーする方法はありません。

struct技術的には、ウィジェットは、実装の外部からは見えないフィールドをコアに含めることができるためmemcpy()、手動でカウントしてバイト数を指定する場合を除いて、ダムを使用してビットをコピーすることもできません。リテラルを使用します。

そうは言っても、十分なウィジェットがプロパティを介して十分な状態を公開し、コピーが引き続き機能し、おそらくわずかな不具合しか示さない可能性も十分にあります。それは確かにかなりクールなハックでしょう。おそらくgtk-devel-listメーリングリストで、コアGTK+開発者に直接質問することをお勧めします。

于 2010-06-09T07:07:11.817 に答える
3

プロパティを使用したクローンは実行可能なソリューションです。

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確実に) 使用できます。

プロパティで公開されていない状態の多くは気にしませんが (すべての適切なウィジェットは、 で使用できるようにプロパティによって完全に定義されている必要がありますGtkBuilder)、多くのコーナー ケースにより、堅牢なクローン作成が非常に困難になります (インターフェイスとコンテナーが最初に使用されるものです)。頭に来ます)。

于 2010-06-13T00:26:33.660 に答える