# 使用 fyne 编写一个计算器程序

## 控件布局

display := widget.NewEntry()
display.MultiLine = true

digits := []string{
"7", "8", "9", "×",
"4", "5", "6", "-",
"1", "2", "3", "+",
}
var digitBtns []fyne.CanvasObject
for _, val := range digits {
digitBtns = append(digitBtns, widget.NewButton(val, input(display, val)))
}
digitContainer := fyne.NewContainerWithLayout(
layout.NewGridLayout(4),
digitBtns...)

input回调后面介绍。

• AC：清空显示框；
• +/-：切换正负号；
• %将数字变为百分数，即除以 100。

clearBtn := widget.NewButton("AC", clear(display))
signBtn := widget.NewButton("+/-", sign(display))
percentBtn := widget.NewButton("%", percent(display, "%"))
divideBtn := widget.NewButton("÷", input(display, "÷"))
clearContainer := fyne.NewContainerWithLayout(
layout.NewGridLayout(4),
clearBtn,
signBtn,
percentBtn,
divideBtn,
)

zeroBtn := widget.NewButton("0", input(display, "0"))
dotBtn := widget.NewButton(".", input(display, "."))
equalBtn := widget.NewButton("=", equals(display))
zeroContainer := fyne.NewContainerWithLayout(
layout.NewGridLayout(2),
zeroBtn,
fyne.NewContainerWithLayout(
layout.NewGridLayout(2),
dotBtn,
equalBtn,
),
)

container := fyne.NewContainerWithLayout(
layout.NewVBoxLayout(),
display,
clearContainer,
digitContainer,
zeroContainer,
)

## 按钮响应

func clear(display *widget.Entry) func() {
return func() {
display.Text = ""
display.Refresh()
}
}

func sign(display *widget.Entry) func() {
return func() {
lines := strings.Split(display.Text, "\n")
if len(lines) == 0 {
return
}

line := lines[len(lines)-1]
value, err := strconv.ParseInt(line, 10, 64)
if err != nil {
return
}
lines[len(lines)-1] = strconv.FormatInt(-value, 10)
display.Text = strings.Join(lines, "\n")
}
}

func input(display *widget.Entry, value string) func() {
return func() {
display.Text += value
display.Refresh()
}
}

func equals(display *widget.Entry) func() {
return func() {
lines := strings.Split(display.Text, "\n")
if len(lines) == 0 {
return
}

line := lines[len(lines)-1]
line = strings.Trim(line, "+÷×")
exprLine := strings.Replace(line, "÷", "/", -1)
exprLine = strings.Replace(exprLine, "×", "*", -1)
expr, _ := govaluate.NewEvaluableExpression(exprLine)
result, _ := expr.Evaluate(nil)
line += "=\n"
line += fmt.Sprint(result)
display.Text = line
display.Refresh()
}
}

## 打包

\$ fyne package -os windows -icon icon.jpg

## 参考

1. fyne GitHub：https://github.com/fyne-io/fyne
2. fyne 官网：https://fyne.io/
3. fyne 官方入门教程：https://developer.fyne.io/tour/introduction/hello.html
4. Go 每日一库 GitHub：https://github.com/darjun/go-daily-lib

0 条评论

• ### Go 每日一库之 fyne

Go 语言生态中，GUI 一直是短板，更别说跨平台的 GUI 了。fyne向前迈了一大步。fyne 是 Go 语言编写的跨平台的 UI 库，它可以很方便地移植到...

• ### Go 每日一库之 nutsdb

nutsdb是一个完全由 Go 编写的简单、快速、可嵌入的持久化存储。nutsdb与我们之前介绍过的buntdb有些类似，但是支持List、Set、Sorted...

• ### Go 每日一库之 plot

本文介绍 Go 语言的一个非常强大、好用的绘图库——plot。plot内置了很多常用的组件，基本满足日常需求。同时，它也提供了定制化的接口，可以实现我们的个性化...

• ### CentOS 7 部署RabbitMQ 服务

版权声明：本文为木偶人shaon原创文章，转载请注明原文地址，非常感谢。 https://b...

• ### 7-开发板接入小五物联实现远程控制(Air202模块+单片机)

这一节为教程最终版功能演示,现在不必深究,早晚自己全部都会实现的(静静的跟着我学哈)

• ### js事件循环

之前有看过一些事件循环的博客，不过一阵子没看就发现自己忘光了，所以决定来自己写一个博客总结下！

• ### 7-开发板接入小五物联实现远程控制(Air202模块+单片机)

https://www.cnblogs.com/yangfengwu/p/9337033.html

• ### Flutter 实现虎牙/斗鱼 弹幕效果

弹幕的实现原理非常简单，即将一条弹幕从左侧平移到右侧，当然我们要计算弹幕垂直方向上的偏移，不然所有的弹幕都会在一条直线上，相互覆盖。平移代码如下：

• ### Flutter 实现虎牙/斗鱼 弹幕功能

弹幕的实现原理非常简单，即将一条弹幕从左侧平移到右侧，当然我们要计算弹幕垂直方向上的偏移，不然所有的弹幕都会在一条直线上，相互覆盖。平移代码如下：

• ### 安卓逆向系列教程（三）静态分析工具

几年之前，我们要破解 APK，可能需要用到 apktool、dex2jar、jd-gui 以及 smali2java 等工具。还需要在控制台中键入命令，但现在有...