英文:
How to extend fyne BaseWidget - go gives error "type *SimpleCard has no field or method super"
问题
我正在尝试扩展fyne小部件,使其具有带有背景的简单可点击内容。我搜索了fyne小部件,找到了一个类似的示例,可以用作起点,类似于List/ListItem。
我基本上复制了列表项代码并进行了一些调整。
它看起来与fyne文档中的简单示例相似。但由于某种未知的原因,Go给了我一个错误,我不知道原因是什么,也不知道如何修复它:
custom_widget/simple_card.go:80:24: c.card.super undefined (type *SimpleCard has no field or method super)
这是模块的代码(custom_widget/simple_card.go):
package custom_widget
import (
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
	"log"
)
// 声明符合接口的类型。
var _ fyne.Widget = (*SimpleCard)(nil)
var _ fyne.Tappable = (*SimpleCard)(nil)
type SimpleCard struct {
	widget.BaseWidget
	onTapped   func()
	background *canvas.Rectangle
	content    fyne.CanvasObject
	selected   bool
}
func NewSimpleCard(content fyne.CanvasObject, tapped func()) *SimpleCard {
	card := &SimpleCard{onTapped: tapped, content: content}
	card.ExtendBaseWidget(card)
	return card
}
// CreateRenderer是一个将此custom_widget链接到其渲染器的私有方法。
func (c *SimpleCard) CreateRenderer() fyne.WidgetRenderer {
	c.ExtendBaseWidget(c)
	c.background = canvas.NewRectangle(theme.SelectionColor())
	c.background.Hide()
	objects := []fyne.CanvasObject{c.background, c.content}
	// NewBaseRenderer和BaseRenderer是从
	// https://github.com/fyne-io/fyne/blob/master/internal/widget/base_renderer.go
	// 复制过来的,因为在fyne中,这些功能被标记为internal!?
	return &SimpleCardRenderer{NewBaseRenderer(objects), c}
}
func (c *SimpleCard) Tapped(_ *fyne.PointEvent) {
	log.Println("我被点击了")
	if c.onTapped != nil {
		c.selected = true
		c.Refresh()
		c.onTapped()
	}
}
// 声明符合WidgetRenderer接口的类型。
var _ fyne.WidgetRenderer = (*SimpleCardRenderer)(nil)
type SimpleCardRenderer struct {
	BaseRenderer
	card *SimpleCard
}
// MinSize计算SimpleCardRenderer的最小大小。
// 这基于状态指示器的大小和子对象的大小。
func (c *SimpleCardRenderer) MinSize() fyne.Size {
	return c.card.content.MinSize()
}
// 布局SimpleCardRenderer custom_widget的组件。
func (c *SimpleCardRenderer) Layout(size fyne.Size) {
	c.card.background.Resize(size)
	c.card.content.Resize(size)
}
func (c *SimpleCardRenderer) Refresh() {
	if c.card.selected {
		c.card.background.FillColor = theme.SelectionColor()
		c.card.background.Show()
	} else {
		c.card.background.Hide()
	}
	c.card.background.Refresh()
	canvas.Refresh(c.card.super()) // 编译器错误!
}
希望这可以帮助你解决问题。
英文:
I'm trying to extend fyne widget to have a simple clickable content with background.
I searched fyne widgets to find an example that could be used as a starter and found something similar in List/ListItem.
I basically copied the list item code and adapted it a little bit.
It does look similar to the simpler example on fyne documentation.
But for some unknown reason go gives me an error and I don't know what the cause is or how I can fix it:
custom_widget/simple_card.go:80:24: c.card.super undefined (type *SimpleCard has no field or method super)
Here is the code of the module (custom_widget/simple_card.go):
package custom_widget
import (
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
	"log"
)
// Declare conformity with interfaces.
var _ fyne.Widget = (*SimpleCard)(nil)
var _ fyne.Tappable = (*SimpleCard)(nil)
type SimpleCard struct {
	widget.BaseWidget
	onTapped   func()
	background *canvas.Rectangle
	content    fyne.CanvasObject
	selected   bool
}
func NewSimpleCard(content fyne.CanvasObject, tapped func()) *SimpleCard {
	card := &SimpleCard{onTapped: tapped, content: content}
	card.ExtendBaseWidget(card)
	return card
}
// CreateRenderer is a private method to Fyne which links this custom_widget to its renderer.
func (c *SimpleCard) CreateRenderer() fyne.WidgetRenderer {
	c.ExtendBaseWidget(c)
	c.background = canvas.NewRectangle(theme.SelectionColor())
	c.background.Hide()
	objects := []fyne.CanvasObject{c.background, c.content}
	// NewBaseRenderer and BaseRenderer are copied from
	// https://github.com/fyne-io/fyne/blob/master/internal/widget/base_renderer.go
	// because the functionality is marked internal in fyne !?
	return &SimpleCardRenderer{NewBaseRenderer(objects), c}
}
func (c *SimpleCard) Tapped(_ *fyne.PointEvent) {
	log.Println("I have been tapped")
	if c.onTapped != nil {
		c.selected = true
		c.Refresh()
		c.onTapped()
	}
}
// Declare conformity with the WidgetRenderer interface.
var _ fyne.WidgetRenderer = (*SimpleCardRenderer)(nil)
type SimpleCardRenderer struct {
	BaseRenderer
	card *SimpleCard
}
// MinSize calculates the minimum size of a SimpleCardRenderer.
// This is based on the size of the status indicator and the size of the child object.
func (c *SimpleCardRenderer) MinSize() fyne.Size {
	return c.card.content.MinSize()
}
// Layout the components of the SimpleCardRenderer custom_widget.
func (c *SimpleCardRenderer) Layout(size fyne.Size) {
	c.card.background.Resize(size)
	c.card.content.Resize(size)
}
func (c *SimpleCardRenderer) Refresh() {
	if c.card.selected {
		c.card.background.FillColor = theme.SelectionColor()
		c.card.background.Show()
	} else {
		c.card.background.Hide()
	}
	c.card.background.Refresh()
	canvas.Refresh(c.card.super()) // compiler error !
}
答案1
得分: 1
删除您创建的所有渲染器类型,并在CreateRenderer中只返回widget.NewSimpleRenderer(container.NewMax(c.background, c.content))。这比您想象的要简单。
从主要小部件中复制代码通常不是最好的方法,因为我们有快捷方式和/或必须支持比您自己的小部件更多的功能。
英文:
Remove all of the renderer type you created and in the CreateRenderer just return widget.NewSimpleRenderer(container. It is simpler than you think.
.NewMax(c.background, c.content))
Copying code out of the main widgets is often not the best way as we have shortcuts and/or must support more functionality than your own widgets.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论