使用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可识别的属性。
修复步骤
- 导出Go结构体字段
将BondItem的字段改为大写开头,确保gotk4能访问:
type BondItem struct { Figi string Name string }
添加数据时同步修改字段名:
BondsData.Append(BondItem{ Figi: "erfegre", Name: "name1", })
- 替换模板工厂为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)
- 清理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,提问作者Антон Киселев
相关产品推荐
相关产品推荐

