如何扩展fyne的BaseWidget – Go会报错”type *SimpleCard没有super字段或方法”

huangapple go评论90阅读模式
英文:

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
.NewMax(c.background, c.content))
. It is simpler than you think.

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.

huangapple
  • 本文由 发表于 2022年10月6日 17:08:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/73971257.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定