数值输入
在传统意义上,GUI程序使用回调来定制小部件的操作。Fyne不公开插入自定义回调来捕获小部件上的事件,但它不需要
相反,我们可以简单地使用Type Embedding并扩展小部件,使其仅能输入数值。
首先创建一个新的类型结构,我们将其称为numericEntry。
type numericalEntry struct {
widget.Entry
}
正如在扩展现有小部件中所提到的,我们遵循了良好的实践,并创建了一个扩展BaseWidget的构造函数。
func newNumericalEntry() *numericalEntry {
entry := &numericalEntry{}
entry.ExtendBaseWidget(entry)
return entry
}
现在我们需要使条目只接受数字。这可以通过重写作为fyne.Focusable接口一部分的TypedRune(rune)方法来实现。这将允许我们拦截从按键接收的符文的标准处理,并只通过我们想要的符文。在这个方法中,我们将使用一个条件来检查符文是否匹配0到9之间的任何数字。如果是,我们将其委托给嵌入条目的标准TypedRune(rune)方法。如果没有,我们就忽略输入。这个实现将只允许输入整数,但如果需要,可以很容易地扩展到将来检查其他键。
func (e *numericalEntry) TypedRune(r rune) {
if r >= '0' && r <= '9' {
e.Entry.TypedRune(r)
}
}
如果我们想更新实现以允许十进制数字,我们可以简单地添加。以及,添加到允许的符文列表中(某些语言在小数点上使用逗号)。
func (e *numericalEntry) TypedRune(r rune) {
if (r >= '0' && r <= '9') || r == '.' || r == ',' {
e.Entry.TypedRune(r)
}
}
这样,输入现在只允许用户在按键时输入数值。但是,粘贴快捷方式仍然允许输入文本。为了解决这个问题,我们可以覆盖作为fyne.Shortcutable接口一部分的TypedShortcut(fyne.S快捷方式)方法。首先,我们需要执行一个类型断言,以检查给定的快捷方式是否为*fyne.ShortcutPaste类型。如果不是,我们可以将快捷方式委托回嵌入的条目。如果是,我们使用strconv.ParseFloat()检查剪贴板内容是否是数字的(如果您只允许整数,strconv.Atoi()就可以了),然后如果剪贴板内容可以无错误地解析,则将快捷方式委派回嵌入的条目。
func (e *numericalEntry) TypedShortcut(shortcut fyne.Shortcut) {
paste, ok := shortcut.(*fyne.ShortcutPaste)
if !ok {
e.Entry.TypedShortcut(shortcut)
return
}
content := paste.Clipboard.Content()
if _, err := strconv.ParseFloat(content, 64); err == nil {
e.Entry.TypedShortcut(shortcut)
}
}
另外,我们还可以确保移动操作系统打开数字键盘,而不是默认键盘。这可以通过首先导入fyne.io/fyne/v2/driver/mobile包,然后覆盖作为m?mobile.Keyboardable接口一部分的Keyboard()mobile.Keyboard Type方法来实现。在函数内部,我们只需返回mobile.NumberKeyboard类型。
func (e *numericalEntry) Keyboard() mobile.KeyboardType {
return mobile.NumberKeyboard
}
最后,生成的代码可能看起来像这样:
package main
import (
"strconv"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/driver/mobile"
"fyne.io/fyne/v2/widget"
)
type numericalEntry struct {
widget.Entry
}
func newNumericalEntry() *numericalEntry {
entry := &numericalEntry{}
entry.ExtendBaseWidget(entry)
return entry
}
func (e *numericalEntry) TypedRune(r rune) {
if (r >= '0' && r <= '9') || r == '.' || r == ',' {
e.Entry.TypedRune(r)
}
}
func (e *numericalEntry) TypedShortcut(shortcut fyne.Shortcut) {
paste, ok := shortcut.(*fyne.ShortcutPaste)
if !ok {
e.Entry.TypedShortcut(shortcut)
return
}
content := paste.Clipboard.Content()
if _, err := strconv.ParseFloat(content, 64); err == nil {
e.Entry.TypedShortcut(shortcut)
}
}
func (e *numericalEntry) Keyboard() mobile.KeyboardType {
return mobile.NumberKeyboard
}
func main() {
a := app.New()
w := a.NewWindow("Numerical")
entry := newNumericalEntry()
w.SetContent(entry)
w.ShowAndRun()
}