You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用gotk4时GTK4无法识别Go对象字段的问题求助

问题:Go对象绑定GTK4模板时无法识别字段

使用gotk4开发GTK4 GUI,将Go对象绑定到GTK4模板后列表显示空内容,报错提示Type GObject does not have a property name 'name'。

bond.ui 代码片段

<object class="GtkScrolledWindow">
    <property name="height-request">400</property>
    <child>
        <object class="GtkColumnView">
            <property name="model">
                <object class="GtkSingleSelection" id="selection_model"/>
            </property>
            <property name="tab-behavior">cell</property>
            <child>
                <object class="GtkColumnViewColumn" id="figi_column">
                    <property name="expand">True</property>
                    <property name="factory">
                        <object class="GtkBuilderListItemFactory">
                            <property name="bytes"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <template class="GtkColumnViewCell">
    <property name="child">
      <object class="GtkLabel">
        <property name="xalign">0</property>
        <binding name="label">
          <lookup name="name" type="GObject">
            <lookup name="item">GtkColumnViewCell</lookup>
          </lookup>
        </binding>
      </object>
    </property>
  </template>
</interface>]]></property>
                        </object>
                    </property>
                    <property name="title">FIGI</property>
                </object>
            </child>
        </object>
    </child>
</object>

Go 代码片段

import (
    _ "embed"
    "fmt"
    "github.com/diamondburned/gotk4/pkg/core/gioutil"
    "github.com/diamondburned/gotk4/pkg/core/glib"
    "github.com/diamondburned/gotk4/pkg/gtk/v4"
    "log"
)

//go:embed bond.ui
var uiXML string

type BondItem struct {
    figi string
    name string
}

var BondsData = gioutil.NewListModel[BondItem]()

func main() {
app := gtk.NewApplication("anton_helper.antonkisselev", gio.ApplicationFlagsNone)

    builder := gtk.NewBuilderFromString(uiXML)
    window := builder.GetObject("bond_window").Cast().(*gtk.Window)

    table := builder.GetObject("selection_model").Cast().(*gtk.SingleSelection)

    BondsData.Append(BondItem{
        figi: "erfegre",
        name: "name1",
    })
    BondsData.Append(BondItem{
        figi: "eefyyyyegre",
        name: "name2",
    })
    table.SetModel(BondsData)

    app.AddWindow(window)
    window.SetVisible(true)
}

报错信息

2024/12/23 23:04:09 ERROR Error building template for list item: .:0:0: Type `GObject` does not have a property name `name` priority=4 code_file=../../../gtk/gtkbuilderlistitemfactory.c code_line=110 code_func=gtk_builder_list_item_factory_setup glib_domain=Gtk
解决方案

错误原因

  • Go结构体字段未导出:BondItem的name和figi字段是小写开头,属于Go未导出字段,gotk4无法访问这些字段并暴露给GTK属性系统。
  • 模板绑定逻辑错误:UI模板中用type="GObject"查找属性,但BondItem不是GObject子类,GTK无法直接识别其字段。
  • gioutil.ListModel的限制:gioutil.NewListModel仅提供基础列表模型功能,不会自动将Go结构体字段转为GTK可识别的属性。

修复步骤

  1. 导出Go结构体字段
    将BondItem的字段改为大写开头,确保gotk4能访问:
type BondItem struct {
    Figi string
    Name string
}

添加数据时同步修改字段名:

BondsData.Append(BondItem{
    Figi: "erfegre",
    Name: "name1",
})
  1. 替换模板工厂为Go代码实现
    由于Go结构体不是GObject,无法通过UI模板的lookup直接绑定字段,需改用gtk.SignalListItemFactory手动处理数据绑定:
// 创建信号工厂替代UI里的BuilderListItemFactory
factory := gtk.NewSignalListItemFactory()

// 设置setup回调:创建列表项的Label控件
factory.ConnectSetup(func(listItem *gtk.ListItem) {
    label := gtk.NewLabel("")
    label.SetXAlign(0)
    listItem.SetChild(label)
})

// 设置bind回调:将数据绑定到Label
factory.ConnectBind(func(listItem *gtk.ListItem) {
    // 获取列表项对应的Go对象
    item := listItem.Item().Value().(BondItem)
    // 获取之前创建的Label
    label := listItem.Child().(*gtk.Label)
    // 设置Label显示内容
    label.SetLabel(item.Name)
})

// 将工厂绑定到列
figiColumn := builder.GetObject("figi_column").Cast().(*gtk.ColumnViewColumn)
figiColumn.SetFactory(factory)
  1. 清理UI模板中的工厂配置
    移除bond.ui中figi_column的factory部分,改为如下结构:
<object class="GtkColumnViewColumn" id="figi_column">
    <property name="expand">True</property>
    <property name="title">FIGI</property>
</object>

完整修复后的核心代码

func main() {
    app := gtk.NewApplication("anton_helper.antonkisselev", gio.ApplicationFlagsNone)

    builder := gtk.NewBuilderFromString(uiXML)
    window := builder.GetObject("bond_window").Cast().(*gtk.Window)

    table := builder.GetObject("selection_model").Cast().(*gtk.SingleSelection)

    // 创建自定义列表项工厂
    factory := gtk.NewSignalListItemFactory()
    factory.ConnectSetup(func(listItem *gtk.ListItem) {
        label := gtk.NewLabel("")
        label.SetXAlign(0)
        listItem.SetChild(label)
    })
    factory.ConnectBind(func(listItem *gtk.ListItem) {
        item := listItem.Item().Value().(BondItem)
        label := listItem.Child().(*gtk.Label)
        label.SetLabel(item.Name)
    })

    // 绑定工厂到列
    figiColumn := builder.GetObject("figi_column").Cast().(*gtk.ColumnViewColumn)
    figiColumn.SetFactory(factory)

    // 添加测试数据
    BondsData.Append(BondItem{
        Figi: "erfegre",
        Name: "name1",
    })
    BondsData.Append(BondItem{
        Figi: "eefyyyyegre",
        Name: "name2",
    })
    table.SetModel(BondsData)

    app.AddWindow(window)
    window.SetVisible(true)

    // 启动应用
    if code := app.Run(nil); code != 0 {
        log.Fatal(code)
    }
}

内容的提问来源于stack exchange,提问作者Антон Киселев

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 07:48:11