2

gobject を継承しようとしていますが、とりわけ G_PARAM_CONSTRUCT_ONLY プロパティの値を変更して、次の子クラスが気にする必要がないようにしたいと考えています。

これを示す例を次に示します。GtkComboBox には、デフォルト値が FALSE の「has-entry」という構造のみのプロパティがあります。クラス AI では、クラス B が気にする必要がないように、この値を TRUE に変更したいと考えています。

            GtkComboBoxClass <-- AClass <-- BClass
"has-entry"      FALSE            TRUE

最初の素朴なアプローチは、A の instance_init 関数で g_object_set() を使用することでしたが、役に立ちませんでした。

次のアイデアは、g_object_class_find_property() で GParamSpec を取得し、A の class_init 関数の g_param_value_set_default() でデフォルト値を変更することでした。しかし、これはすべての GtkComboBoxClass 派生オブジェクトのデフォルトを変更すると思います。

私が思いついた最良のアイデア: g_object_class_override_property() が新しい GParamSpec を作成する場合、これを見つけて、A の class_init 関数でデフォルト値を設定できます。しかし、ドキュメンテーションはこれについて一言も漏らしません。

だから私の質問:これはこれを達成するための有効で意図的な方法ですか、それともより良い解決策がありますか?

これまでに試した:

  • インスタンス init() 内の g_object_set():
    • 起動時に警告なし
    • 無効
  • GObjectClass->constructor() の g_object_set():
    • 起動時に警告なし
    • 無効
    • 終了時の警告: GtkCellCiew から GtkEntry への無効なキャスト
  • GObjectClass->constructed() の g_object_set():
    • 開始時の警告: 構築後に設定できません

ありがとうステファン

4

2 に答える 2

3

サブクラスでプロパティを設定する場合、そのプロパティは構成のみであり、仮想関数の代わりにconstructed仮想関数を使用して呼び出す必要があります。g_object_set()init

コンストラクトのみとしてマークされたプロパティは、コンストラクタ自体で指定されていない限り、デフォルト値を使用して構築中に適用されますg_object_new()。これは、が呼び出さinit()れた後に値が設定されるため、内部で構成のみのプロパティを設定するだけでは不十分であることを意味します。init()一方、constructed()仮想関数はコンストラクターのプロパティが適用された後に呼び出されるため、そこでデフォルト値をオーバーライドすることができます。

于 2013-05-15T20:58:44.477 に答える
1

自分でこれに答える:

gobject ソースを調べると、constructor() に指定されたプロパティ リストに、すべての G_PARAM_CONSTRUCT および G_PARAM_CONSTRUCT_ONLY プロパティと、それらのデフォルト値または指定値が含まれていることがわかります。

これらの値の変更は文書化されていません (少なくとも私は見つけられませんでした) が、機能します。親コンストラクターに連鎖する前に、このリストで構築時のプロパティ値を変更する必要があります。非構築プロパティは後で設定する必要があります。サンプル コードは次のようになります。

static GObject *constructor(GType gtype, guint n_properties, GObjectConstructParam *properties) {
    GObject *object;
    guint i;
    gchar const *name;
    GObjectConstructParam *property;

    for (i = 0, property = properties; i < n_properties; ++i, ++property) {
        name = g_param_spec_get_name(property->pspec);
        if (!strcmp(name, "has-entry")) // is G_PARAM_CONSTRUCT_ONLY
            g_value_set_boolean(property->value, TRUE);
    }

    object = G_OBJECT_CLASS(parent_class)->constructor(gtype, n_properties, properties);

    g_object_set(object, "entry-text-column", TEXT_COLUMN, NULL);

    return object;
}
于 2013-05-16T16:29:51.160 に答える