无法扩展 fyne 的小部件



(这里有许多新细节。

我正在尝试(非常努力(扩展一些 Fyne 小部件的功能。基本上,我需要实现或"覆盖"右键单击"选择","按钮","编辑"等内容。我也需要对其他一些行为进行微小的改变。

我尝试以各种方式扩展现有小部件。我所做的一切都会导致编译失败、恐慌或奇怪和不正确的行为。下面的答案提供了Button解决方案的声明,但它并不完整。当我将相同的技术应用于选择时,尝试左键单击时它会惊慌失措。

恐慌是

panic: interface conversion: fyne.Canvas is nil, not *glfw.glCanvas

回想起来,这就是我最初失败的地方,也是促使我尝试越来越复杂的方法的原因,但没有一个奏效。按钮和选择显然有不同的要求。

(很抱歉"不接受",但另一种选择是数小时的尝试,并且对我尝试的东西没有信心 - 即使它避免了恐慌 - 是正确的和长期的解决方案。声称 Fyne 小部件是可扩展的 - 要求改进文档以显示如何扩展似乎是合理的,因为幼稚的尝试并不统一工作。

在这里,我尝试使用答案中的技术扩展我关心的小部件。我本以为所有这些小部件的行为都是相同的,模化了TappedSecondary的覆盖。他们通常不会。 正确的答案显然比下面的答案要复杂得多。以下是我基于下面给出的代码的发现:

扩展按钮(如答案所示(:小部件。当鼠标进入该区域时,按钮会改变颜色。扩展版本没有。单击时,两种形式都不会改变按钮的外观(我通常期望从任何 GUI 中得到这一点,也许缺少其他东西?扩展版本确实捕获了TappedSecondary。

扩展选择(如上所示(:左键单击恐慌。正确捕获右键单击。

扩展标签:您必须添加一个无所事事的点击功能才能使其与所需的界面匹配,但是可以捕获右键单击,一切似乎都很好。

扩展条目:它捕获了TappedSecondary,正如预期的那样,这意味着我没有获得通常的下拉菜单。左键单击(移动光标(不会在新位置重绘光标,但内部光标位置确实会发生变化(退格键将删除新位置的字符,然后正确重绘所有内容(。

扩展检查:点击辅助被捕获。 左键单击会导致调用 OnChanged(并且每次正确传递的布尔值都会交替(,但永远不会绘制复选标记。

据我今天所知,这些是我需要扩展的唯一小部件,所以当它使列出的小部件像往常一样工作时,我会认为答案是完整的,除了我得到 TappedSecondary。理想的答案是指向某处在线的新文档,该文档为所有小部件类型提供了完整的示例,以保留现有行为的方式(除非您故意覆盖该行为(。

总体印象:以最微不足道的方式扩展小部件可能会在响应鼠标事件时更改或破坏绘制小部件的某些方面,包括"选择"中的死机和"输入"、"按钮"和"选中"中缺少图形更改。我没有覆盖任何现有的 Tapped(( 函数,所以我不知道为什么会这样。


//About contains name string, value string and other fields we don't care about
type HasAbout interface {
GetAbout() *About
}
//loses reaction to mouse movement
type myButton struct {
widget.Button
about *About
}
func (m *myButton) TappedSecondary(*fyne.PointEvent) {
log.Println("Right Click") //works
}
func (m *myButton) GetAbout() *About {
return m.about
}
func newMyButton(label string, tapped func()) *myButton {
ret := &myButton{}
ret.ExtendBaseWidget(ret)
ret.Text = label
ret.OnTapped = tapped
return ret
}
//panic on left click
type mySelect struct {
widget.Select
about *About
}
func (m *mySelect) TappedSecondary(at *fyne.PointEvent) {
log.Println("Right Click", m.about.name, *at) //works
}
func (m *mySelect) GetAbout() *About {
return m.about
}
func newMySelect(about *About) *mySelect {
ret := &mySelect{}
ret.ExtendBaseWidget(ret)
ret.about = about
//widget.Renderer(ret).Layout(ret.MinSize()) //from NewSelect, but did not fix panic
return ret
}
//must override Tapped, and then all seems well
type myLabel struct {
widget.Label
about *About
}
func (m *myLabel) TappedSecondary(at *fyne.PointEvent) {
log.Println("Right Click Label", m.GetAbout().name, *at)
}
//must also implement this or we don't get TappedSecondary
func (m *myLabel) Tapped(at *fyne.PointEvent) {
}
func (m *myLabel) GetAbout() *About {
return m.about
}
func newMyLabel(about *About) *myLabel {
ret := &myLabel{}
ret.ExtendBaseWidget(ret)
ret.about = about
ret.Text = about.value
return ret
}
//lose the ability to see cursor changes on left click.
//correctly, lose the usual dropdown menu on right click
type myEntry struct {
widget.Entry
about *About
}
func (m *myEntry) TappedSecondary(at *fyne.PointEvent) {
log.Println("Right Click Entry", m.Text, *at)
}
func (m *myEntry) GetAbout() *About {
return m.about
}
func newMyEntry(about *About) *myEntry {
ret := &myEntry{}
ret.ExtendBaseWidget(ret)
ret.about = about
return ret
}

//lose the ability to see check changes you made with left click.
type myCheck struct {
widget.Check
about *About
}
func (m *myCheck) TappedSecondary(at *fyne.PointEvent) {
log.Println("Right Click myCheck", m.Text, *at) //works
}

func (m *myCheck) GetAbout() *About {
return m.about
}
func newMyCheck(about *About) *myCheck {
ret := &myCheck{}
ret.ExtendBaseWidget(ret)
ret.about = about
ret.Text = about.value
ret.OnChanged = func(v bool) {fmt.Println("Check is ", v)} //works
return ret
}
//driver, from original answer, given new tests
func main() {
about := About{}
about.name = "hi"
about.value = "Whee"
a := app.New()
w := a.NewWindow("Hello")
w.SetContent(widget.NewVBox(
newMyButton("Right tap me", func() {
log.Println("Normal callback")
}),
newMySelect(&about),
newMyLabel(&about),
newMyEntry(&about),
newMyCheck(&about),
widget.NewButton("X", func(){}) , //to compare against
),
)
w.ShowAndRun()
}

从库中复制代码在这里会分散注意力 - 完全可以扩展小部件,所以我会回答原始意图而不是修复错误......

您可以通过将核心小部件嵌入到结构中,然后添加或覆盖功能来扩展核心构件。关键是调用ExtendBaseWidget以便内部正确注册您的重写类型。下面的代码演示如何创建一个响应右键单击的新按钮。

package main
import (
"log"
"fyne.io/fyne"
"fyne.io/fyne/app"
"fyne.io/fyne/widget"
)
type myButton struct {
widget.Button
}
func (m *myButton) TappedSecondary(*fyne.PointEvent) {
log.Println("Right Click")
}
func newMyButton(label string, tapped func()) *myButton {
ret := &myButton{}
ret.ExtendBaseWidget(ret)
ret.Text = label
ret.OnTapped = tapped
return ret
}
func main() {
a := app.New()
w := a.NewWindow("Hello")
w.SetContent(widget.NewVBox(
newMyButton("Right tap me", func() {
log.Println("Normal callback")
}),
))
w.ShowAndRun()
}

相关内容

  • 没有找到相关文章

最新更新