2

我尝试继承一个 gobject,除其他外,还想更改 G_PARAM_CONSTRUCT_ONLY 属性的值,这样下一个子类就不必关心了。

下面是一个描述这一点的例子: GtkComboBox 有一个名为“has-entry”的仅构造属性,默认值为 FALSE。在 AI 类中,想要将此值更改为 TRUE,这样 B 类就不需要关心了。

            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 函数中设置它的默认值。但是文档并没有对此一言不发。

所以我的问题是:这是一种可行的、有意的方式来实现这一点,还是有更好的解决方案?

到目前为止尝试过:

  • g_object_set() 在实例 init() 中:
    • 启动时没有警告
    • 没有效果
  • 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 回答