master
dustoair 3 years ago
commit be56dcc7f7

9
.gitignore vendored

@ -0,0 +1,9 @@
.idea
go.sum
*.jpeg
*.png
log.txt
logs
*.log
uploads
*.exe

@ -0,0 +1,28 @@
package Application
import (
"fmt"
"github.com/Knetic/govaluate"
"testing"
)
/*
*
@author: sre
@date: 2022/8/22 0022
@desc: todo
*
*/
func TestEquel(t *testing.T) {
str := "1--2"
expr, err := govaluate.NewEvaluableExpression(str)
if err != nil {
fmt.Println("NewEvaluableExpression eror:", err)
}
result, err := expr.Evaluate(nil)
if err != nil {
fmt.Println("Evaluate error:", err)
}
fmt.Println(result)
}

@ -0,0 +1,168 @@
package Application
import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/widget"
"github.com/Knetic/govaluate"
"strconv"
"strings"
)
/**
@author: sre
@date: 2022/8/22 0022
@desc: todo
**/
// MainShow 主界面函数
func MainShow(w fyne.Window) {
//先创建一个widget.Entry对象设置可显示多行
display := widget.NewEntry()
display.MultiLine = true
//其它数字和符号控件都用widget.Button来表示。
//按钮也分为两种,一种是没有特殊效果的,点击后直接在显示框中添加对应的字符即可。
//一种是有特殊效果的例如清空显示框AC、进行计算=)。
//中间三行按钮都是前一种我们使用GridLayout来布局每行显示 4 个:
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 := container.New(
layout.NewGridLayout(4),
digitBtns...)
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 := container.New(
layout.NewGridLayout(2),
zeroBtn,
container.New(
layout.NewGridLayout(2),
dotBtn,
equalBtn,
),
)
//最后我们将所有部分用垂直的BoxLayout组合到一起
container := container.New(
layout.NewVBoxLayout(),
display,
clearContainer,
digitContainer,
zeroContainer,
//copyright,
)
w.SetContent(container)
}
// clear 清空按钮响应比较简单直接将显示框的Text设置为空即可
func clear(display *widget.Entry) func() {
return func() {
display.Text = ""
display.Refresh()
}
}
// sign设计在显示框中显示两行第一行是上次计算的表达式第二行是本次的。
// 切换正负号在本次只输入一个数字时将该数字的正负号进行切换:
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 percent(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
}
valueFloat := float64(value) / 100
valueStr := strconv.FormatFloat(valueFloat, 'f', -1, 64)
lines[len(lines)-1] = valueStr
//lines[len(lines)-1] = strconv.FormatInt(-value, 10)
display.Text = strings.Join(lines, "\n")
display.Refresh()
}
}
// input 输入回调——将对应字符串拼接到显示框中 =号不算
func input(display *widget.Entry, value string) func() {
return func() {
fmt.Println("ui type value:", value)
display.Text += value
display.Refresh()
}
}
// equals 计算表达式的函数 go get github.com/Knetic/govaluate
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, err := govaluate.NewEvaluableExpression(exprLine)
if err != nil {
display.Text = line + "=" + err.Error() + "\n"
display.Refresh()
return
}
result, err := expr.Evaluate(nil)
if err != nil {
fmt.Println(err)
display.Text = line + "=" + err.Error() + "\n"
display.Refresh()
return
}
line = line + "=" + fmt.Sprint(result) + "\n"
display.Text = line
display.Refresh()
}
}

@ -0,0 +1,128 @@
package framework
import (
"fmt"
"freeCaculator/global"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/cmd/fyne_settings/settings"
"fyne.io/fyne/v2/theme"
"net/url"
)
/*
*
@author: sre
@date: 2022/8/22 0022
@desc: todo
*
*/
func MakeMenu(a fyne.App, w fyne.Window) *fyne.MainMenu {
newItem := fyne.NewMenuItem("新建", func() {
fmt.Println("新建")
})
checkedItem := fyne.NewMenuItem("选中", func() {
global.MenuCheckFileChosen = !global.MenuCheckFileChosen
w.SetMainMenu(MakeMenu(a, w))
fmt.Println("选中")
})
checkedItem.Checked = global.MenuCheckFileChosen
disabledItem := fyne.NewMenuItem("禁用", func() {
fmt.Println("禁用")
})
disabledItem.Disabled = true
otherItem := fyne.NewMenuItem("其他", func() {
fmt.Println("其他")
})
otherItem.ChildMenu = fyne.NewMenu("",
fyne.NewMenuItem("项目", func() { fmt.Println("菜单 新建->其他->项目") }),
fyne.NewMenuItem("邮件", func() { fmt.Println("菜单 新建->其他->邮件") }),
fyne.NewMenuItem("doc", func() { fmt.Println("菜单 新建->其他->doc") }),
)
newItem.ChildMenu = fyne.NewMenu("",
fyne.NewMenuItem("文件", func() { fmt.Println("菜单 新建->文件") }),
fyne.NewMenuItem("目录", func() { fmt.Println("菜单 新建->目录") }),
otherItem,
)
settingsItem := fyne.NewMenuItem("设置", func() {
w := a.NewWindow("Fyne 设置")
w.SetContent(settings.NewSettings().LoadAppearanceScreen(w))
w.Resize(fyne.NewSize(480, 480))
w.Show()
})
cutItem := fyne.NewMenuItem("剪切", func() {
shortcutFocused(&fyne.ShortcutCut{
Clipboard: w.Clipboard(),
}, w)
})
copyItem := fyne.NewMenuItem("复制", func() {
shortcutFocused(&fyne.ShortcutCopy{
Clipboard: w.Clipboard(),
}, w)
})
pasteItem := fyne.NewMenuItem("粘贴", func() {
shortcutFocused(&fyne.ShortcutPaste{
Clipboard: w.Clipboard(),
}, w)
})
findItem := fyne.NewMenuItem("查找", func() { fmt.Println("菜单 查找") })
fullScreenSwitchItem := fyne.NewMenuItem("切换当前", func() {
w.SetFullScreen(!w.FullScreen())
})
fullScreenFullItem := fyne.NewMenuItem("切换到全屏", func() {
w.SetFullScreen(true)
})
fullScreenFormItem := fyne.NewMenuItem("切换到窗口", func() {
w.SetFullScreen(false)
})
themeDarkItem := fyne.NewMenuItem("暗色", func() {
a.Settings().SetTheme(theme.DarkTheme())
})
themeLightItem := fyne.NewMenuItem("亮色", func() {
a.Settings().SetTheme(theme.LightTheme())
})
themeCustomItem := fyne.NewMenuItem("高对比度", func() {
a.Settings().SetTheme(NewCustomTheme())
})
helpMenu := fyne.NewMenu("帮助",
fyne.NewMenuItem("文档", func() {
u, _ := url.Parse("https://developer.fyne.io")
_ = a.OpenURL(u)
}),
fyne.NewMenuItem("关于", func() {
u, _ := url.Parse("https://sre.ink")
_ = a.OpenURL(u)
}),
fyne.NewMenuItemSeparator(),
fyne.NewMenuItem("支持", func() {
u, _ := url.Parse("https://fyne.io/support/")
_ = a.OpenURL(u)
}),
fyne.NewMenuItemSeparator(),
fyne.NewMenuItem("赞助", func() {
u, _ := url.Parse("https://fyne.io/sponsor/")
_ = a.OpenURL(u)
}))
// a quit item will be appended to our first (File) menu
file := fyne.NewMenu("文件", newItem, checkedItem, disabledItem)
if !fyne.CurrentDevice().IsMobile() {
file.Items = append(file.Items, fyne.NewMenuItemSeparator(), settingsItem)
}
return fyne.NewMainMenu(
file,
fyne.NewMenu("编辑", cutItem, copyItem, pasteItem, fyne.NewMenuItemSeparator(), findItem),
helpMenu,
fyne.NewMenu("全屏", fullScreenSwitchItem, fyne.NewMenuItemSeparator(), fullScreenFullItem, fullScreenFormItem),
fyne.NewMenu("主题", themeDarkItem, themeLightItem, themeCustomItem),
)
}
func shortcutFocused(s fyne.Shortcut, w fyne.Window) {
if focused, ok := w.Canvas().Focused().(fyne.Shortcutable); ok {
focused.TypedShortcut(s)
}
}

@ -0,0 +1,105 @@
package framework
import (
"freeCaculator/global"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/cmd/fyne_demo/tutorials"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
/*
*
@author: sre
@date: 2022/8/22 0022
@desc: todo
*
*/
func ShowNav(w fyne.Window) {
a := fyne.CurrentApp()
content := container.NewMax()
title := widget.NewLabel("组件名称")
intro := widget.NewLabel("An introduction would probably go\nhere, as well as a")
intro.Wrapping = fyne.TextWrapWord
setTutorial := func(t tutorials.Tutorial) {
if fyne.CurrentDevice().IsMobile() {
child := a.NewWindow(t.Title)
global.TopWindow = child
child.SetContent(t.View(global.TopWindow))
child.Show()
child.SetOnClosed(func() {
global.TopWindow = w
})
return
}
title.SetText(t.Title)
intro.SetText(t.Intro)
content.Objects = []fyne.CanvasObject{t.View(w)}
content.Refresh()
}
tutorial := container.NewBorder(
container.NewVBox(title, widget.NewSeparator(), intro), nil, nil, nil, content)
// 设置窗口内容
if fyne.CurrentDevice().IsMobile() {
w.SetContent(makeNav(setTutorial, false))
} else {
split := container.NewHSplit(makeNav(setTutorial, true), tutorial)
split.Offset = 0.2
w.SetContent(split)
}
}
func makeNav(setTutorial func(tutorial tutorials.Tutorial), loadPrevious bool) fyne.CanvasObject {
a := fyne.CurrentApp()
tree := &widget.Tree{
ChildUIDs: func(uid string) []string {
return tutorials.TutorialIndex[uid]
},
IsBranch: func(uid string) bool {
children, ok := tutorials.TutorialIndex[uid]
return ok && len(children) > 0
},
CreateNode: func(branch bool) fyne.CanvasObject {
return widget.NewLabel("Collection Widgets")
},
UpdateNode: func(uid string, branch bool, obj fyne.CanvasObject) {
t, ok := tutorials.Tutorials[uid]
if !ok {
fyne.LogError("Missing tutorial panel: "+uid, nil)
return
}
obj.(*widget.Label).SetText(t.Title)
},
OnSelected: func(uid string) {
if t, ok := tutorials.Tutorials[uid]; ok {
a.Preferences().SetString(global.PreferenceCurrentTutorial, uid)
setTutorial(t)
}
},
}
if loadPrevious {
currentPref := a.Preferences().StringWithFallback(global.PreferenceCurrentTutorial, "欢迎")
tree.Select(currentPref)
}
themes := container.New(layout.NewGridLayout(2),
widget.NewButton("Dark", func() {
a.Settings().SetTheme(theme.DarkTheme())
}),
widget.NewButton("Light", func() {
a.Settings().SetTheme(theme.LightTheme())
}),
)
return container.NewBorder(nil, themes, nil, nil, tree)
}

@ -0,0 +1,72 @@
package framework
import (
"image/color"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/theme"
)
var (
purple = &color.NRGBA{R: 128, G: 0, B: 128, A: 255}
orange = &color.NRGBA{R: 198, G: 123, B: 0, A: 255}
grey = &color.Gray{Y: 123}
)
// customTheme is a simple demonstration of a bespoke theme loaded by a Fyne app.
type customTheme struct {
}
func (customTheme) Color(c fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color {
switch c {
case theme.ColorNameBackground:
return purple
case theme.ColorNameButton, theme.ColorNameDisabled:
return color.Black
case theme.ColorNamePlaceHolder, theme.ColorNameScrollBar:
return grey
case theme.ColorNamePrimary, theme.ColorNameHover, theme.ColorNameFocus:
return orange
case theme.ColorNameShadow:
return &color.RGBA{R: 0xcc, G: 0xcc, B: 0xcc, A: 0xcc}
default:
return color.White
}
}
func (customTheme) Font(style fyne.TextStyle) fyne.Resource {
return theme.DarkTheme().Font(style)
}
func (customTheme) Icon(n fyne.ThemeIconName) fyne.Resource {
return theme.DefaultTheme().Icon(n)
}
func (customTheme) Size(s fyne.ThemeSizeName) float32 {
switch s {
case theme.SizeNamePadding:
return 8
case theme.SizeNameInlineIcon:
return 20
case theme.SizeNameScrollBar:
return 10
case theme.SizeNameScrollBarSmall:
return 5
case theme.SizeNameText:
return 18
case theme.SizeNameHeadingText:
return 30
case theme.SizeNameSubHeadingText:
return 25
case theme.SizeNameCaptionText:
return 15
case theme.SizeNameInputBorder:
return 1
default:
return 0
}
}
func NewCustomTheme() fyne.Theme {
return &customTheme{}
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,18 @@
package global
import "fyne.io/fyne/v2"
/**
@author: sre
@date: 2022/8/22 0022
@desc: todo
**/
const PreferenceCurrentTutorial = "当前指南"
var (
ResourceAppPng = resourceAppPng
TopWindow fyne.Window
MenuCheckFileChosen = true
APPTitle = "计算器"
)

@ -0,0 +1,39 @@
module freeCaculator
go 1.19
require (
fyne.io/fyne/v2 v2.2.3
github.com/Knetic/govaluate v3.0.0+incompatible
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394
github.com/flopp/go-findfont v0.1.0
)
require (
fyne.io/systray v1.10.1-0.20220621085403-9a2652634e93 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe // indirect
github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 // indirect
github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 // indirect
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 // indirect
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect
github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 // indirect
github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 // indirect
github.com/stretchr/testify v1.7.2 // indirect
github.com/tevino/abool v1.2.0 // indirect
github.com/yuin/goldmark v1.4.0 // indirect
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd // indirect
golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee // indirect
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect
)

@ -0,0 +1,91 @@
package main
import (
"fmt"
"freeCaculator/Application"
"freeCaculator/framework"
"freeCaculator/global"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"github.com/flopp/go-findfont"
"log"
"os"
"strings"
"time"
)
/*
*
@author: sre
@date: 2022/8/22 0022
@desc: todo
*
*/
func init() {
//fyne原生并不支持中文所以其界面上显示和输入汉字会出错。可用init函数引用字体的方式解决。
//go get github.com/flopp/go-findfont
fontPaths := findfont.List()
for _, fontPath := range fontPaths {
fmt.Println(fontPath)
//楷体:simkai.ttf 黑体:simhei.ttf
if strings.Contains(fontPath, "simhei.ttf") {
err := os.Setenv("FYNE_FONT", fontPath)
if err != nil {
return
}
break
}
}
}
//go:generate fyne bundle -package global -o global/bundled.go assets
func main() {
// 创建程序
//_ = os.Setenv("FYNE_FONT", "./data/fonts/awesome.ttf")
a := app.NewWithID("org.yangqiao.picUploader")
a.SetIcon(global.ResourceAppPng)
//a.SetIcon(theme.FyneLogo())
logLifecycle(a)
//a.Settings().SetTheme(theme.LightTheme()) //SetTheme():设置应用的主题,默认为 DarkTheme。
w := a.NewWindow(global.APPTitle) //// 创建窗口对象、传入窗口名称
global.TopWindow = w
w.SetMainMenu(framework.MakeMenu(a, w))
w.SetMaster()
w.SetOnClosed(func() {
fmt.Println("窗口退出 打印剪切板内容")
fmt.Println(w.Clipboard().Content())
})
go func() {
time.Sleep(time.Second * 5)
}()
//主界面框架布局
Application.MainShow(w)
//demo界面框架布局
//ShowNav(w)
w.Resize(fyne.NewSize(640, 460)) //设置窗口尺寸。
//w居中显示
w.CenterOnScreen()
// 窗口的显示和运行
w.ShowAndRun()
}
func logLifecycle(a fyne.App) {
a.Lifecycle().SetOnStarted(func() {
log.Println("生存期: 开始")
})
a.Lifecycle().SetOnStopped(func() {
log.Println("生存期: 结束")
})
a.Lifecycle().SetOnEnteredForeground(func() {
log.Println("生存期: 进入前置窗口")
})
a.Lifecycle().SetOnExitedForeground(func() {
log.Println("生存期: 退出前置窗口")
})
}

@ -0,0 +1 @@
//go:generate fyne bundle -package global -o global/bundled.go assets
Loading…
Cancel
Save