这两天在用Golang写图形化工具,看了fyne的文档就开始着手开发,发现自己写的效果较差。在网上找了大佬的文章跟着学了一遍练手,按照类别整理了笔记。在后续开发过程中学习到的新知识与遇到的问题及解决方案都会更新在这篇文章中。
Alikh Khan大佬文章地址:https://blogvali.com/category/fyne-golang-gui/
Alikh Khan大佬视频链接:https://www.youtube.com/watch?v=k6o0SFXGRYw&list=PL5vZ49dm2gshlo1EIxFNcQFBUfLFoHPfp

官方文档地址:https://docs.fyne.io/

1.程序窗口

1.Title

设定程序标题

package main  

import (
"fmt"

"fyne.io/fyne/v2/app") // Importing Fyne in my project

func main() {
fmt.Println("Test Fyne…")
// Start with go mod init myapp to create a package
// we will create Our First Fyne Project
// Our first line of code will creating a new app
a := app.New()

// Now we will create a new window
w := a.NewWindow("I want to change my title") // You can you any title of your app
w.ShowAndRun() // Finally Running our App
}

2.Resize Window

重新设置窗口大小

package main  

// importing fyne v2

import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app")

func main() {
a := app.New()
w := a.NewWindow("My title for 2nd tutorial")

//Resizin our fyne app window
// first one is width // 2nd value is height
w.Resize(fyne.NewSize(700, 200))
w.ShowAndRun() // Running our App
}

3.Dark/LightTheme

设置主题

// Light Theme
a.Settings().SetTheme(theme.LightTheme())
// Dark Theme
a.Settings().SetTheme(theme.DarkTheme())

4.自定义App Icon

4.1. Custom App Icon

自定义项目图标

package main

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"io/ioutil"
"net/http"
"path/filepath"
)

func main() {
//New App
a := app.New()
// New Window
w := a.NewWindow("How to change App ICON")
// New title bar
// New App ICON // How to use custom ICON ?
r, _ := LoadResourceFromPath("./svg.ico")
w.SetIcon(r)
// Resize
w.Resize(fyne.NewSize(400, 400))
// Show and run
w.ShowAndRun()
}

// //////// Paste Code here
// Resource represents a single binary resource, such as an image or font.// A resource has an identifying name and byte array content.
// The serialised path of a resource can be obtained which may result in a
// blocking filesystem write operation.
type Resource interface {
Name() string
Content() []byte
}

// StaticResource is a bundled resource compiled into the application.// These resources are normally generated by the fyne_bundle command included in
// the Fyne toolkit.
type StaticResource struct {
StaticName string
StaticContent []byte
}

// Name returns the unique name of this resource, usually matching the file it// was generated from.
func (r *StaticResource) Name() string {
return r.StaticName
}

// Content returns the bytes of the bundled resource, no compression is applied// but any compression on the resource is retained.
func (r *StaticResource) Content() []byte {
return r.StaticContent
}

// NewStaticResource returns a new static resource object with the specified// name and content. Creating a new static resource in memory results in
// sharable binary data that may be serialised to the location returned by
// CachePath().
func NewStaticResource(name string, content []byte) *StaticResource {
return &StaticResource{
StaticName: name,
StaticContent: content,
}
}

// LoadResourceFromPath creates a new StaticResource in memory using the contents of the specified file.
func LoadResourceFromPath(path string) (Resource, error) {
bytes, err := ioutil.ReadFile(filepath.Clean(path))
if err != nil {
return nil, err
}
name := filepath.Base(path)
return NewStaticResource(name, bytes), nil
}

// LoadResourceFromURLString creates a new StaticResource in memory using the body of the specified URL.
func LoadResourceFromURLString(urlStr string) (Resource, error) {
res, err := http.Get(urlStr)
if err != nil {
return nil, err
}
defer res.Body.Close()
bytes, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
name := filepath.Base(urlStr)
return NewStaticResource(name, bytes), nil
}

4.2. Custom App Icon 2

package main  

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
)

func main() {
// New app
a := app.New()
r, _ := fyne.LoadResourceFromPath("./svg.ico")
// change icon
a.SetIcon(r)
// New window/ title
w := a.NewWindow("change app icon")
//resize
w.Resize(fyne.NewSize(400, 400))
w.ShowAndRun()
}

5.Menu

5.1.Main Menu

package main  

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app")

func main() {
// New app
a := app.New()
//app title
w := a.NewWindow("Main Menu")
// resize window
w.Resize(fyne.NewSize(400, 400))
// first item
menuItem := &fyne.Menu{
Label: "File",
Items: nil, // we will add sub items in next video
}
menu := fyne.NewMainMenu(menuItem) // main menu
// to remove error add & // Show main menu
w.SetMainMenu(menu) /// we are done :)
//
w.ShowAndRun()
}

5.2.Menu Items

package main

// import fyne
import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
)

func main() {
// new app
a := app.New()
// new window
w := a.NewWindow("Main Menu")
// resize window
w.Resize(fyne.NewSize(400, 400))
// Menu Items
menuItem1 := fyne.NewMenuItem("New", func() { fmt.Println("New pressed") })
menuItem2 := fyne.NewMenuItem("Save", func() { fmt.Println("Save pressed") })
menuItem3 := fyne.NewMenuItem("edit", nil)
// New Menu
newMenu := fyne.NewMenu("File", menuItem1, menuItem2, menuItem3)
// creating new main menu
menu := fyne.NewMainMenu(newMenu)
// setting new menu
w.SetMainMenu(menu)
w.ShowAndRun()
}

5.3. Child Menu

package main  

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app")

func main() {
// new app
a := app.New()
// title of app
w := a.NewWindow("Child Menu")
// resize window
w.Resize(fyne.NewSize(400, 400))
// new menu items
//first parameter is label, 2nd is function
item1 := fyne.NewMenuItem("edit", nil)
item2 := fyne.NewMenuItem("details", nil)
item3 := fyne.NewMenuItem("home", nil)
item4 := fyne.NewMenuItem("run", nil)
// child menu
item1.ChildMenu = fyne.NewMenu(
"", // leave label blank
fyne.NewMenuItem("copy", nil), // child menu items
fyne.NewMenuItem("cut", nil),
fyne.NewMenuItem("paste", nil),
)
// create child menu for 2nd item
item2.ChildMenu = fyne.NewMenu(
"", // leave label blank
fyne.NewMenuItem("books", nil), // child menu items
fyne.NewMenuItem("magzine", nil),
fyne.NewMenuItem("notebook", nil),
)
// create child menu for third item
item3.ChildMenu = fyne.NewMenu(
"", // leave label blank
fyne.NewMenuItem("school", nil), // child menu items
fyne.NewMenuItem("college", nil),
fyne.NewMenuItem("university", nil),
)
NewMenu1 := fyne.NewMenu("File", item1, item2, item3, item4)
NewMenu2 := fyne.NewMenu("Help", item1, item2, item3, item4)
// main menu
menu := fyne.NewMainMenu(NewMenu1, NewMenu2)
// setup menu
w.SetMainMenu(menu) /// we are done :)
// show and run
w.ShowAndRun()
}

6. Scroll

1.Vertical scroll

c := container.NewVScroll(
// your widgets goes here
)

2.Horizontal scroll

c := container.NewHScroll(
// your widgets goes here
)

两者多元素用NewHBox 或 NewVBox

container.NewHBox( // New Horizontal Box
red, // for red Rectangle
blue, // for blue Rectangle
),

3.设置滚轮方向

c.Direction = container.ScrollHorizontalOnly

示例:

package main  

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"image/color"
)

func main() {
// New app
a := app.New()
// new windown and title
w := a.NewWindow("Scroll")
// resize
w.Resize(fyne.NewSize(400, 400))
// red rectangle
red := canvas.NewRectangle(
color.NRGBA{R: 255, G: 0, B: 0, A: 255})
red.SetMinSize(fyne.NewSize(400, 400))
// blue rectangle
blue := canvas.NewRectangle(
color.NRGBA{R: 0, G: 0, B: 255, A: 255})
blue.SetMinSize(fyne.NewSize(400, 400))
// New Scroll & Vbox
c := container.NewVScroll(
container.NewHBox( // New Horizontal Box
red,
blue,
),
)
// Change scroll direction
c.Direction = container.ScrollHorizontalOnly
// setup content
w.SetContent(c)
// show and run
w.ShowAndRun()
}

2.Widget

1.Label

使用NewWindow方法可以创建text label
传入参数必须为字符串
整形->字符串

fmt.Sprintf("%d",myInt)

bool->字符串

fmt.Sprintf("%t",mybool)

textlabel示例

package main

import (
// importing fyne
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)

func main() {
// New app
a := app.New()
//New Window
w := a.NewWindow("Here is my title for 3 tutorial")

// Resize Windows
w.Resize(fyne.NewSize(300, 300))
// Our First widget
labelX := widget.NewLabel("I can write anything")
w.SetContent(labelX)

w.ShowAndRun() // Running app
}

2.Butotn

2.1.创建button

创建按钮

widget.NewButton()
//可传入两个参数,第一个是按钮中的文字
//第二个是点击按钮时调用的函数
widget.NewButton("button Name", func() {})

button示例

package main

// importing fyne
import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)

func main() {

// creating new app
a := app.New()
// New window
w := a.NewWindow("Here is my title for 4th tutorial")
// resizing my window
w.Resize(fyne.NewSize(400, 400))
// Now Its Time to use BUTTONs
// First value is button name // 2nd value is any function
btn := widget.NewButton("button Name", func() {
// Our is ready
fmt.Println("Here is Go Button")
})
// using our button on
w.SetContent(btn)
// Running app
w.ShowAndRun()
}

设定大小的话,button会自动填充

2.2.点击Button更改Button数值

package main

// importing fyne
import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
"image/color"
"math/rand"
)

func main() {
// creating new app
a := app.New()
// New window and title
w := a.NewWindow("Random Number Generator")
// Resize
w.Resize(fyne.NewSize(400, 400))
// Label
label1 := canvas.NewText("Rand Num Gen", color.Black)
label1.TextSize = 40
// Button
btn1 := widget.NewButton("Generate", func() {
// Ui is ready
// Now logic
rand1 := rand.Intn(1000)
label1.Text = fmt.Sprint(rand1) //conver int to string
label1.Refresh() // refresh and render UI
})
// Showing and setup content
w.SetContent(
// more than on widget so use container newVbox
container.NewVBox(
label1,
btn1,
),
)
//show and run
w.ShowAndRun()
}

2.3. Button color,background,image

(not effective)

package main

import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/widget"
"image/color"
)

func main() {
a := app.New()
w := a.NewWindow("Colored Button")
//resize window
w.Resize(fyne.NewSize(400, 400))
// Let show out button on screen
w.SetContent(
container.NewVBox(
red_button(),
red_button(),
red_button(),
red_button(),
// let show / display buttons
blue_button(),
green_button(),
img_button(),
),
)
w.ShowAndRun() // show and run app
}

// first colored button
func red_button() *fyne.Container { // return type
btn := widget.NewButton("Visit", nil) // button widget
// button color
btn_color := canvas.NewRectangle(
color.NRGBA{R: 255, G: 0, B: 0, A: 255})
// container for colored button
container1 := container.New(
// layout of container
layout.NewMaxLayout(),
// first use btn color
btn_color,
// 2nd btn widget
btn,
)
// our button is ready
return container1
}

// Blue button
// copy previous button code and change it
func blue_button() *fyne.Container { // return type
btn := widget.NewButton("Visit", nil) // button widget
// button color
btn_color := canvas.NewRectangle(
color.NRGBA{R: 05, G: 0, B: 255, A: 255})
// container for colored button
container1 := container.New(
// layout of container
layout.NewMaxLayout(),
// first use btn color
btn_color,
// 2nd btn widget
btn,
)
// our button is ready
return container1
}

// Green button
// copy and paste previous button
func green_button() *fyne.Container { // return type
btn := widget.NewButton("Visit", nil) // button widget
// button color
btn_color := canvas.NewRectangle(
color.NRGBA{R: 0, G: 255, B: 0, A: 255})
// container for colored button
container1 := container.New(
// layout of container
layout.NewMaxLayout(),
// first use btn color
btn_color,
// 2nd btn widget
btn,
)
// our button is ready
return container1
}

// button with image as background
func img_button() *fyne.Container { // return type
btn := widget.NewButton("Visit", nil) // button widget
// img button color
img := canvas.NewImageFromFile("D:\\jpg")
// container for colored button
container1 := container.New(
// layout of container
layout.NewMaxLayout(),
// first use btn color
img,
// 2nd btn widget
btn,
)
// our button is ready
return container1
}

2.4. Disabled Button

不可使用的按钮

package main  

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)

func main() {
// new app
a := app.New()
// new window and title
w := a.NewWindow("Disabled Button")
// resize window
w.Resize(fyne.NewSize(400, 400))
disabled_button := widget.NewButton("Disabled",
func() {})
disabled_button.Disable()
//this will disable btn
w.SetContent(
container.NewVBox(
disabled_button,
),
)
// show and run
w.ShowAndRun()
}

2.5.调整Entry,Button大小

自定义Entry、button大小示例

package main

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)

func main() {
// New app
a := app.New()
// New Window & title
w := a.NewWindow("Resize any widget")
//Resize main/parent window
w.Resize(fyne.NewSize(400, 400))
// 1st Widget Entry
entry := widget.NewEntry()
entry.SetPlaceHolder("Enter your name")
entry.Resize(fyne.NewSize(250, 30)) // my widget size
entry.Move(fyne.NewPos(40, 50)) // position of widget
entry_email := widget.NewEntry()
entry_email.SetPlaceHolder("Enter your email")
entry_email.Resize(fyne.NewSize(250, 30)) // my widget size
entry_email.Move(fyne.NewPos(40, 100)) // position of widget
entry_address := widget.NewEntry()
entry_address.SetPlaceHolder("Enter your name")
entry_address.Resize(fyne.NewSize(250, 30)) // my widget size
entry_address.Move(fyne.NewPos(40, 150)) // position of widget
// button
btn_submit := widget.NewButton("Submit", nil)
btn_submit.Resize(fyne.NewSize(150, 30)) // my widget size
btn_submit.Move(fyne.NewPos(40, 200)) // position of widget
w.SetContent(
container.NewWithoutLayout(
entry,
entry_email,
entry_address,
btn_submit,
),
)
//show and run
w.ShowAndRun()
}

3. Checkbox

3.1. 创建复选框

复选框
两个参数,第一个是复选框名称,第二个是判断复选框是否选中调用的函数

package main

// importing fyne

import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)

func main() {
// New App
a := app.New()
// New Window and title
w := a.NewWindow("Here is check box tutorial title")
// Resizing window of App
w.Resize(fyne.NewSize(400, 400))

// check box widget
checkbox1 := widget.NewCheck("Male", func(b bool) {
if b == true {
fmt.Println("Male")
} else {
fmt.Println("Not Male")
}

})

// set up content
w.SetContent(checkbox1)
// running and showing app
w.ShowAndRun()
}

3.2.复选框数据更新实例

复选框更新label实例

package main

// import fyne
import (
"image/color"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)

func main() {
// new app
a := app.New()
// new title and window
w := a.NewWindow("check Box tutorial")
// resize window
w.Resize(fyne.NewSize(400, 400))
// our first widget
label := canvas.NewText("Your choice is ...", color.Black)
// check box
// first argument is name(string),
// 2nd is function

chk_male := widget.NewCheck("male", func(b bool) {
// change name of label
if b == true {
label.Text = "male"
// refresh
label.Refresh()
} else {
label.Text = "deseleted"
// refresh
label.Refresh()
}
})

// create new one for female
chk_female := widget.NewCheck("female", func(b bool) {
// change name of label
if b == true {
label.Text = "female"
// refresh
label.Refresh()
} else {
label.Text = "deseleted"
label.Show()
// refresh
label.Refresh()
}
})

w.SetContent(
// here we put all our widgets
// we are done...
// lets show content on screen
container.NewVBox(
label,
chk_male,
chk_female,
),
)
w.ShowAndRun()
}

3.3. 复选框控制显示与隐藏widgets

通过复选框实现rectangle的显示与隐藏

package main

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
"image/color"
)

func main() {
// New app
a := app.New()
// New title and window
w := a.NewWindow("Hide and show objects")
w.Resize(fyne.NewSize(400, 400))
// new rectangle
rect := canvas.NewRectangle(color.Black)
rect.Resize(fyne.NewSize(100, 100)) // 100x100 size
rect.Move(fyne.NewPos(50, 50)) // new position of rectangle
// check box to show and hide rectangle or any other object
// first argument is title of check box
// 2nd is function
chkbox := widget.NewCheck("hide", func(b bool) {
if b != true {
rect.Hide()
} else {
rect.Show() // show object/rectangle
}
})
// size of chkbox and position
chkbox.Move(fyne.NewPos(50, 200))
chkbox.Resize(fyne.NewSize(100, 50))
// setup content
w.SetContent(
// container without layout
container.NewWithoutLayout(
rect,
chkbox,
),
)
w.ShowAndRun()
}

4.页面链接

package main

// importing fyne
import (
"net/url"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)

func main() {
// creating new app
a := app.New()
// creating new window
w := a.NewWindow("Here is Hyperlink widget")
w.Resize(fyne.NewSize(400, 400))
// creating url
url, _ := url.Parse("https://google.com")

// hyperLink Widget
// first value is label // 2nd value is URL/ website address
hyperlink := widget.NewHyperlink("Visit me", url)

// setup content
w.SetContent(hyperlink)
w.ShowAndRun() // show and run
}

5.ICON

内容中导入icon

package main

// importing Fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)

func main() {
// creating app
a := app.New()
// create window
w := a.NewWindow("Icon : tutorial")
//resizing windows
w.Resize(fyne.NewSize(400, 400))
// Creating Icon Widget
IconX := widget.NewIcon(theme.CancelIcon())

// setup content
w.SetContent(IconX)
// show windows
w.ShowAndRun()
}

6. Cards

card有3个部分组成

card := widget.NewCard(  
"Here is My Title",
"Here is my SubTitle",
// here you can use any Widget
canvas.NewImageFromFile("c:/dice/dice1.jpg"),
)

示例

package main  

// importing fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/widget"
)

func main() {
// new app
a := app.New()
//New window
w := a.NewWindow("CARDS In Fyne")
// Resize
w.Resize(fyne.NewSize(400, 400))
// Card Widget
card := widget.NewCard(
"Here is My Title",
"Here is my SubTitle",
// here you can use any Widget
canvas.NewImageFromFile("c:/dice/dice1.jpg"),
)

//Showing content
w.SetContent(card)

w.ShowAndRun() //Show and Run App
}

7. Multiline Entry

7.1.创建Multiline Entry

多行输入框,类似textarea

package main  

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)

func main() {
// new app
a := app.New()
// window title
w := a.NewWindow("Multi-Line Entry")
// resize window size
w.Resize(fyne.NewSize(400, 400))
// New Multi line Entry Widget
multilineEntry := widget.NewMultiLineEntry()
const (
loremIpsum = `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.`
)
multilineEntry.SetText(loremIpsum)
//multilineEntry.Wrapping = fyne.TextWrapBreak
//multilineEntry.Wrapping = fyne.TextWrapOff //multilineEntry.Wrapping = fyne.TextTruncate
w.SetContent(multilineEntry)
// show and run
w.ShowAndRun()
}

7.2.调整Mutliline Entry大小

package main

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
"image/color"
)

func main() {
// New App
a := app.New()
// New window and title
w := a.NewWindow("Contact form & Resize widgets")
// Resize window
w.Resize(fyne.NewSize(400, 400))
// title of our form
title := canvas.NewText("Contact Us", color.Black)
title.TextSize = 20 // text font size is 20
title.TextStyle = fyne.TextStyle{Bold: true}
// I need it bold.. you can make it italic
title.Resize(fyne.NewSize(300, 35)) // 300 is width & 35 is height
title.Move(fyne.NewPos(50, 10))
//position my widget
//50 px from left and 10 px from top
// copy / the setting(resize/ postion)
// Name field
entry_name := widget.NewEntry()
entry_name.SetPlaceHolder("Enter your name..")
entry_name.Resize(fyne.NewSize(300, 35))
entry_name.Move(fyne.NewPos(50, 50))
// copy / paste for next widget email :)
entry_email := widget.NewEntry()
entry_email.SetPlaceHolder("Enter your email..")
entry_email.Resize(fyne.NewSize(300, 35))
entry_email.Move(fyne.NewPos(50, 100))
// copy / paste for address
entry_addr := widget.NewEntry()
entry_addr.SetPlaceHolder("Enter your addr..")
entry_addr.Resize(fyne.NewSize(300, 35))
entry_addr.Move(fyne.NewPos(50, 150))
// copy/ paste for last widget
entry_msg := widget.NewMultiLineEntry()
entry_msg.SetPlaceHolder("Enter your message..")
// most important
entry_msg.MultiLine = true // multiline input / text area for message
entry_msg.Resize(fyne.NewSize(300, 140))
entry_msg.Move(fyne.NewPos(50, 200))
// Submit button
submit_btn := widget.NewButton("SUBMIT", nil)
submit_btn.Resize(fyne.NewSize(80, 30))
// button need to be small as compared to textarea
submit_btn.Move(fyne.NewPos(50, 355))
// setup content
// we are going to use container without layout// my favorite
w.SetContent(
container.NewWithoutLayout(
title,
entry_name,
entry_email,
entry_addr,
entry_msg,
submit_btn,
),
)
// Show and run
w.ShowAndRun()
}

8.Accordion items

可折叠框

package main

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)

func main() {
// New app
a := app.New()
// New title
w := a.NewWindow("Accordian - fyne ")
// resize windows size
w.Resize(fyne.NewSize(400, 400))
// Let create items for accoridan
// first argument is title, 2nd is description/details
item1 := widget.NewAccordionItem("A",
widget.NewLabel("A for Apple"))
item2 := widget.NewAccordionItem("B",
widget.NewLabel("B for Ball"))
item3 := widget.NewAccordionItem("C",
widget.NewLabel("C for Cat"))
ac := widget.NewAccordion(item1, item2, item3)
w.SetContent(ac)
w.ShowAndRun()
}

9.Slider 数据绑定

slider 进度条

package main  

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/data/binding"
"fyne.io/fyne/v2/widget"
)

func main() {
// New app
a := app.New()
// New window and title
w := a.NewWindow("Slider & data binding")
// resize
w.Resize(fyne.NewSize(400, 400))
// first slider widget
// 3 arguments // min value, max value, and data source
f := 20.0 // any float value
data := binding.BindFloat(&f)
slider1 := widget.NewSliderWithData(
0, 100, data)
// Slider part is done
// Now lets attach slider value with label
label1 := widget.NewLabelWithData(
binding.FloatToString(data),
)

// we are done :)
// Lets show and setup content
w.SetContent(
container.NewVBox(
label1,
slider1,
),
)
// Show data
w.ShowAndRun()
}

9.登录表单Form

表单以及取消、提交方法

package main

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)

func main() {
// new app
a := app.New()
// new title and window
w := a.NewWindow("New Form")
// resize window
w.Resize(fyne.NewSize(400, 400))
// label empty
label := widget.NewLabel("")
// form widget
form := widget.NewForm(
// new use form items
// 2 arguments
// label, widget
widget.NewFormItem("Username", widget.NewEntry()),
// password
widget.NewFormItem("Password", widget.NewPasswordEntry()),
)
// working on cancel and submit functions of form
form.OnCancel = func() {
label.Text = "Canceled"
label.Refresh()
}
form.OnSubmit = func() {
label.Text = "submitted"
label.Refresh()
}
// we are almost done
w.SetContent(
container.NewVBox(
form,
label,
),
)
w.ShowAndRun()
}

10.List

NewList有3个参数:1.item数量 2.widget类型,可选label、card等 3.更新widgets里的数据
Onselected:被选择时调用
OnUnselected: 当被取消选择时调用

package main

// import fyne
import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)

func main() {
a := app.New()
// window and title
w := a.NewWindow("List View")
// resize
w.Resize(fyne.NewSize(400, 400))
// list View
// 3 arguments
// item count, 3 itmes in list
// widget, I want to use label widget
// update data of widget
list := widget.NewList(
// lets change item count from 3 to 30
func() int { return 30 }, // my list contain 3 items
func() fyne.CanvasObject { return widget.NewLabel("I want to use label") },
// last one
func(lii widget.ListItemID, co fyne.CanvasObject) {
// update data of widget
co.(*widget.Label).SetText("Here is my text")
},
)
list.OnSelected = func(id widget.ListItemID) {
fmt.Println(id)
}

list.OnUnselected = func(id widget.ListItemID) {
fmt.Println(id)
} // setup data on screen
w.SetContent(list)
w.ShowAndRun()
}

11. Table

package main

// import fyne
import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
)

func main() {
// New app
a := app.New()
// new title and window
w := a.NewWindow("Table widget")
// resize
w.Resize(fyne.NewSize(400, 400))
// create table widget
// table is like list , just 2 values, instead of one
table := widget.NewTable(
// row and col . I want to create 3 row , 3 col
func() (int, int) { return 3, 3 },
// Now I want to specify widget. like label, checkbox
func() fyne.CanvasObject { return widget.NewLabel("....") },
// update/details data in widget
func(i widget.TableCellID, obj fyne.CanvasObject) {
// remember it is label and not newlabel
// i is for index
// i.col will set col value
// i.row will present row value
obj.(*widget.Label).SetText(fmt.Sprintf("%d %d", i.Col, i.Row))
},
)
w.SetContent(table)
w.ShowAndRun()
}

12.Toolbar icons

package main

// import fyne
import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)

func main() {
// new app
a := app.New()
// new title and window
w := a.NewWindow("Tool bar - music player ui")
// resize main window
w.Resize(fyne.NewSize(400, 400))
// new widget---- Tool bar
toolbar := widget.NewToolbar(
//toolbar items
widget.NewToolbarAction(
// first argument is icon
// 2nd is action/func(){}
theme.MediaPlayIcon(), func() {
fmt.Println("Play music...")
},
),
// copy paste for other items
// pause
widget.NewToolbarAction(
// first argument is icon
// 2nd is action/func(){}
theme.MediaPauseIcon(), func() {
fmt.Println("Pause music...")
},
),
widget.NewToolbarAction(
// first argument is icon
// 2nd is action/func(){}
theme.MediaStopIcon(), func() {
fmt.Println("Stop music...")
},
),
// spacer widget
widget.NewToolbarSpacer(),
// new item for support
/// copy paste
widget.NewToolbarAction(
// first argument is icon
// 2nd is action/func(){}
theme.HelpIcon(), func() {
fmt.Println("support music...")
},
),
)
// put everthing in a container
// c := container.NewHBox(toolbar)
// letss change container
c := container.NewBorder(
// 5 elements / arguments
// top, right,left,bottom, center
toolbar, nil, nil, nil, widget.NewLabel("Content here"),
)
w.SetContent(c)
w.ShowAndRun()
}

13. Select

package main
// import fyne
import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
func main() {
// New app
a := app.New()
// new title and window
w := a.NewWindow("Select entry widget, drop down")
// resize window
w.Resize(fyne.NewSize(400, 400))
// lets show our selected entry in label
label1 := widget.NewLabel("...")
// dropdown/ select entry
//[]string{} all our option goes in slice
// s is the variable to get the selected value
dd := widget.NewSelect(
[]string{"city1-dehli", "London", "islamabad", "kabul"},
func(s string) {
fmt.Println("I selected %s to live forever..", s)
label1.Text = s
label1.Refresh()
})
// more than one widget. so use container
c := container.NewVBox(dd, label1)
w.SetContent(c)
//show and run
w.ShowAndRun()
}

14.Select Entry Dropdown

可输入、下拉的选择框

package main

// import fyne
import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)

func main() {
// new app
a := app.New()
// new title and window
w := a.NewWindow("Select Entry - DropDown advance")
// resize window
w.Resize(fyne.NewSize(400, 400))
// lets create a label
label1 := widget.NewLabel("...")
// newselectentry widget
// []string{} it take only slice of option
//& you can your options also in run time. Not hardcoded
select_entry := widget.NewSelectEntry([]string{"peshawar", "multan", "gujrat", "kabul", "dehli"})
// what to do with the selected entry ?
// here is what we are going to define
select_entry.OnSubmitted = func(s string) {
fmt.Printf("my city %s is awesome", s)
// update label with our values
label1.Text = s
label1.Refresh()
}
// container .. we have more than one widgets
c := container.NewVBox(
label1,
select_entry,
)
w.SetContent(c)
w.ShowAndRun()
}

enter ->submit

3.Canvas

1.Text与颜色改变

创建text

canvas.NewText

第一个参数是文字内容
第二个参数是颜色

package main

// import Fyne
import (
"image/color"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
)

func main() {
// Create new app
a := app.New()

// Create New Window and Title
w := a.NewWindow("My Canvas Text Tutorial")
// Resize window
w.Resize(fyne.NewSize(400, 400))
// Our Text widget in Canvas
//first value for label/cation // 2nd for color value // Now creating Color
colorx := color.NRGBA{R: 0, G: 0, B: 255, A: 255}
// R is Red and Range is zero to 255
// B is blue and G is Green // A is for alpha for opacity
textX := canvas.NewText("Here is my blue text", colorx)

// Setup widget.
w.SetContent(textX)
w.ShowAndRun() // Show and run App
}

2.Image

2.1. 本地图片加载

本地图片加载

package main

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
)

func main() {
// New app
a := app.New()
// New Window and Title
w := a.NewWindow("Image in Fyne")
// resize window
w.Resize(fyne.NewSize(400, 400))
// Now Image widget
img := canvas.NewImageFromFile("c:/cartoon/health.jpg")

// setup content to show
w.SetContent(img)
// show and run
w.ShowAndRun()
}

2.2.加载网络图片

package main  

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
)

func main() {
// New app
a := app.New()
// New Title and Window
w := a.NewWindow("Load images from internet")
// loading images/assets/icons from computer
//r, _ := plugin.LoadResourceFromPath("c:/assets/tree.jpg")
// Images/assets from internet //r, _ := plugin.LoadResourceFromURLString("https://picsum.photos/200")
r, _ := fyne.LoadResourceFromURLString("https://cdn.jsdelivr.net/gh/Xrect1fy/picorep//img/202404271415252.jpg")
// CAT API Free — http://placekitten.com/g/200/300
// New Random image URL https://picsum.photos/200
img := canvas.NewImageFromResource(r)
// Resize
w.Resize(fyne.NewSize(400, 400))

// Show and Setup content
w.SetContent(img)
w.ShowAndRun()
}

3.Circle

绘制圆形

package main  

// importing fyne

import (
"image/color"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas")

func main() {
// creating app

a := app.New()
//creating new window
w := a.NewWindow("Title : Circle")
// window resize

circle1 := canvas.NewCircle(color.NRGBA{R: 0, G: 0, B: 255, A: 255})
circle1.StrokeColor = color.NRGBA{R: 255, G: 0, B: 0, A: 255}
circle1.StrokeWidth = 33 // Stroke width
//Setup content w.SetContent(circle1)
w.Resize(fyne.NewSize(400, 400))
w.ShowAndRun()
}

4.Rectangle

绘制长方形

package main  

// importing fyne
import (
"image/color"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas")

func main() {
// creating app
a := app.New()
// creating windows
w := a.NewWindow("Rectangle : Canvas")

rect := canvas.NewRectangle(color.Black)
//fill color
rect.FillColor = color.NRGBA{R: 255, G: 255, B: 0, A: 255}
rect.StrokeColor = color.NRGBA{R: 255, G: 0, B: 0, A: 255}
rect.StrokeWidth = 5.0
//setup content
w.SetContent(rect)
//resizing window
w.Resize(fyne.NewSize(400, 400))

w.ShowAndRun() // show and run app
}

5.Line

绘制直线

//创建直线
lineX := canvas.NewLine(color.Black)
//更改颜色
lineX.FillColor = color.NRGBA{R: 255, G: 255, B: 0, A: 255}
//直线边框颜色
lineX.StrokeColor = color.NRGBA{R: 0, G: 255, B: 0, A: 255}
//直线边框宽度
lineX.StrokeWidth = 12.0

直线示例

package main  

// importing fyne
import (
"image/color"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas")

func main() {
// creating new app
a := app.New()
// creating new window and title
w := a.NewWindow("Line : Canvas tutorial")
// resizing my windows
w.Resize(fyne.NewSize(400, 400))
// creating line
lineX := canvas.NewLine(color.Black)
lineX.StrokeColor = color.NRGBA{R: 0, G: 255, B: 0, A: 255}
lineX.StrokeWidth = 12.0
//setup content
w.SetContent(lineX)

// Running app
w.ShowAndRun()
}

6. Gradient

渐变色,使用时查询即可

package main  

// import Fyne
import (
"image/color"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
)
func main() {
// New App
a := app.New()
// New Window and Title
w := a.NewWindow("Gradient : Canvas")
w.Resize(fyne.NewSize(400, 400))
// Radial Gradient
gradient1 := canvas.NewRadialGradient(
color.White, color.NRGBA{R: 255, G: 0, B: 0, A: 255}) // 45 degree angle
// Linear Gradient //gradient2 := canvas.NewLinearGradient( // color.White, color.NRGBA{R: 255, G: 0, B: 0, A: 255}, 270) // 45 degree angle
// Horizontal Gradient //gradient3 := canvas.NewHorizontalGradient( // color.White, color.NRGBA{R: 255, G: 0, B: 0, A: 255})
// Vertical Gradient //gradient4 := canvas.NewVerticalGradient( // color.White, color.NRGBA{R: 255, G: 0, B: 0, A: 255}) // 45 degree angle // setup content
w.SetContent(gradient1)
w.ShowAndRun()
}

4.布局

1.Box布局

box布局
NewHbox 水平盒子 NewVbox 垂直盒子

package main

// importing fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)

func main() {
// creating new app
a := app.New()
// creating new window and title
w := a.NewWindow("Layout NewVBox and NewHbox")
w.Resize(fyne.NewSize(400, 400))
// New button
btn1 := widget.NewButton("click me", func() {
})
label1 := widget.NewLabel("here is my text")
// NewHBox
box1 := container.NewHBox( // Horizontal
btn1,
label1,
)
// NewVBox
// box1 := container.NewVBox( // Vertical // btn1, // label1, // ) // setup content
w.SetContent(
box1,
)
// show and run
w.ShowAndRun()
}

2.NewHSplit/NewVSplit

分割线,将内容分为两部分

package main  

// import Fyne
import (
"image/color"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)

func main() {
// New App
a := app.New()
// New Title And Window
w := a.NewWindow("NewHSplit Widget in Fyne")
//Resize
w.Resize(fyne.NewSize(400, 400))
// 1st widget
label1 := canvas.NewText("Text1", color.Black)
label2 := canvas.NewText("Text2", color.Black)
w1 := widget.NewIcon(theme.CancelIcon())
btn1 := widget.NewButton("Play ", func() {
})
// Setup Content
w.SetContent(
container.NewHSplit(
container.NewVBox(
label1,
w1,
),
// 2nd Section
container.NewVBox(
label2,
btn1,
),
),
)
w.ShowAndRun()
}

3.Layout布局

将长方形移动到屏幕中心
其中

package main

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"image/color"
)

func main() {
// New App
a := app.New()
// New title and window
w := a.NewWindow("Layout = My FAV")
// resize
w.Resize(fyne.NewSize(400, 400))
//Rectangle
Red_RECT := canvas.NewRectangle(color.RGBA{R: 255, G: 0, B: 0, A: 255})
// Size of Rectangle very important
Red_RECT.Resize(fyne.NewSize(50, 50)) // 50x50 pixels
// Position of rectangle on screen
//Red_RECT.Move(fyne.NewPos(0, 0))
// (0,0) x axis & y axis is zero
// I need rectangle at bottom
// our canvas size is 400x400
// and rectangle size is 50x50
// 400-50 = 350 // 350 is bottom for our rectangle
//Red_RECT.Move(fyne.NewPos(350, 350))
//I need my rectangle in center
// so our calculation will be
// 400-50= 350
// now for center divide by 2
// 350/2 = 175
// 175X175
// fyne.NewPos象征长方形左上角坐标
Red_RECT.Move(fyne.NewPos(175, 175))
// Let setup content
// we are going to use container without layout
w.SetContent(
container.NewWithoutLayout(
Red_RECT,
),
)
//show and run
w.ShowAndRun()
}

5.实战项目

1.红绿灯

package main  

// import Fyne
import (
"fmt"
"image/color"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)

func main() {
//颜色
var x uint8 = 0

a := app.New()

w := a.NewWindow("Traffic Lights Project")
w.Resize(fyne.NewSize(400, 400))
fyne.CurrentApp().Settings().SetTheme(theme.DarkTheme())
//绘制三个圆
rect1 := canvas.NewCircle(color.NRGBA{R: 255, G: 255, B: 255, A: 255})
rect1.Resize(fyne.NewSize(50, 50))
rect2 := canvas.NewCircle(color.NRGBA{R: 255, G: 255, B: 255, A: 255})
rect2.Resize(fyne.NewSize(50, 50))
rect3 := canvas.NewCircle(color.NRGBA{R: 255, G: 255, B: 255, A: 255})
rect3.Resize(fyne.NewSize(50, 50))
//四个按钮
btnR := widget.NewButton("Red", func() {
fmt.Printf("%t", true)
//指定颜色前将颜色清空
Reset(rect1, rect2, rect3)
rect1.FillColor = color.NRGBA{R: incrementMove(x), G: 0, B: 0, A: 255}
rect1.Refresh()
})
btnG := widget.NewButton("Green", func() {

Reset(rect1, rect2, rect3)
rect2.FillColor = color.NRGBA{R: 0, G: incrementMove(x), B: 0, A: 255}
rect2.Refresh()
})
btnB := widget.NewButton("Blue", func() {

Reset(rect1, rect2, rect3)
rect3.FillColor = color.NRGBA{R: 0, G: 0, B: incrementMove(x), A: 255}
rect3.Refresh()
})

btnReset := widget.NewButton("Reset", func() {

rect1.FillColor = color.NRGBA{R: 255, G: 255, B: 255, A: 255}
rect2.FillColor = color.NRGBA{R: 255, G: 255, B: 255, A: 255}
rect3.FillColor = color.NRGBA{R: 255, G: 255, B: 255, A: 255}
rect1.Refresh()
rect2.Refresh()
rect3.Refresh()
})
//布局
w.SetContent(
container.NewHSplit(
container.NewGridWithRows(

7,

layout.NewSpacer(),
rect1,
layout.NewSpacer(),
rect2,
layout.NewSpacer(),
rect3,
layout.NewSpacer(),
),

container.NewGridWithRows(
9,
layout.NewSpacer(),
btnR,

btnG,

btnB,

btnReset,
layout.NewSpacer(),
),
),
)
w.ShowAndRun()
}
//变色
func incrementMove(x uint8) (a uint8) {
if x == 255 {
x = 0
} else if x == 0 {
x = 255
}

return x
}
//颜色清空
func Reset(rect1, rect2, rect3 *canvas.Circle) {

rect1.FillColor = color.NRGBA{R: 255, G: 255, B: 255, A: 255}
rect2.FillColor = color.NRGBA{R: 255, G: 255, B: 255, A: 255}
rect3.FillColor = color.NRGBA{R: 255, G: 255, B: 255, A: 255}
rect1.Refresh()
rect2.Refresh()
rect3.Refresh()
}

2.骰子游戏

package main  

// import fyne
import (
"fmt"
"math/rand"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)

func main() {
// New app
a := app.New()
// New window and Title
w := a.NewWindow("Dicee Game")
// resize Window
w.Resize(fyne.NewSize(400, 400))
// image of Dice
img := canvas.NewImageFromFile("c:/dice/dice6.jpg")
img.FillMode = canvas.ImageFillOriginal
// button
btn1 := widget.NewButton("Play", func() {
// UI is finished.. Now Logic part
rand := rand.Intn(6) + 1 // ignore zero 0+1=1
img.File = fmt.Sprintf("c:/dice/dice%d.jpg", rand)
img.Refresh()
})
// Setup content and finish UI
w.SetContent(
// NewVBox.. More than on Widgets
container.NewVBox(
img,
btn1,
),
)
// show and run app
w.ShowAndRun()
}

3.查询ip、城市、国家

package main

// import Fyne
import (
"encoding/json"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
"io/ioutil"
"net/http"
)

//IP信息结构体
type IP struct {
Query string
Country string
City string
}

func main() {
// New app
a := app.New()
// New Title and Window
w := a.NewWindow("What is my IP?")
// Resize
w.Resize(fyne.NewSize(400, 400))
// Let Creat UI First
//Title
labelTitle := widget.NewLabel("What is my IP?")
labelIP := widget.NewLabel("Your IP is …")
label_Value := widget.NewLabel("…")
label_City := widget.NewLabel("…")
label_Country := widget.NewLabel("…")
//点击按钮则更新Label为我的信息
btn := widget.NewButton("Run", func() {
// Logic
label_Value.Text = myIP()
label_Value.Refresh()
label_City.Text = myCity()
label_City.Refresh()
label_Country.Text = myContry()
label_Country.Refresh()
})
//布局 垂直box
w.SetContent(
container.NewVBox(
labelTitle,
labelIP,
label_Value,
label_City,
label_Country,
btn,
),
)
// Show and Run
w.ShowAndRun()
}

//获取ip
func myIP() string {
req, err := http.Get("http://ip-api.com/json/")
if err != nil {
return err.Error()
}

defer req.Body.Close()
body, err := ioutil.ReadAll(req.Body)
if err != nil {
return err.Error()
}
var ip IP
json.Unmarshal(body, &ip)

return ip.Query
}

//获取城市
func myCity() string {
req, err := http.Get("http://ip-api.com/json/")
if err != nil {
return err.Error()
}

defer req.Body.Close()
body, err := ioutil.ReadAll(req.Body)
if err != nil {
return err.Error()
}
var ip IP
json.Unmarshal(body, &ip)

return ip.City
}

//获取国家
func myContry() string {
req, err := http.Get("http://ip-api.com/json/")
if err != nil {
return err.Error()
}

defer req.Body.Close()
body, err := ioutil.ReadAll(req.Body)
if err != nil {
return err.Error()
}
var ip IP
json.Unmarshal(body, &ip)

return ip.Country
}

4. weather API

API获取数据实战+json转换

package main

// import fyne

import (
"encoding/json"
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"image/color"
"io/ioutil"
"net/http"
)

func main() {
// new app
a := app.New()
//New title and window
w := a.NewWindow("Weather API & Fyne")

//Consuming Api
res, err := http.Get("https://api.openweathermap.org/data/2.5/weather?q=peshawar&APPID=88a3325d8b543b9103c71abe0ebc15ef")
if err != nil {
fmt.Print(err)
}

defer res.Body.Close()

body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Print(err)
}

//
weather, err := UnmarshalWeather(body)
if err != nil {
fmt.Print(err)
}

// Now we are almost done
img := canvas.NewImageFromFile("c:/assets/weather.jpg")
img.FillMode = canvas.ImageFillOriginal
label1 := canvas.NewText("Weather Api & fyne", color.Black)
label1.TextStyle = fyne.TextStyle{Bold: true}
label2 := canvas.NewText(fmt.Sprintf("Country %s", weather.Sys.Country), color.Black)
label5 := canvas.NewText(fmt.Sprintf("City %s", weather.Name), color.Black)
label3 := canvas.NewText(fmt.Sprintf("wind speed %.2f", weather.Wind.Speed), color.Black)
label4 := canvas.NewText(fmt.Sprintf("TEMP %.2f F", weather.Main.Temp), color.Black)

w.SetContent(
container.NewVBox(

label1,
img,
label2,
label5,
label3,
label4,
),
)

w.Resize(fyne.NewSize(500, 500))
w.ShowAndRun() // show and run app
}

// Use api.QuickType.io to Convert Json response

// This file was generated from JSON Schema using quicktype, do not modify it directly.
// To parse and unparse this JSON data, add this code to your project and do:
//
// weather, err := UnmarshalWeather(bytes)
// bytes, err = weather.Marshal()

// package main

func UnmarshalWeather(data []byte) (Weather, error) {
var r Weather
err := json.Unmarshal(data, &r)
return r, err
}

func (r *Weather) Marshal() ([]byte, error) {
return json.Marshal(r)
}

type Weather struct {
Coord Coord `json:"coord"`
Weather []WeatherElement `json:"weather"`
Base string `json:"base"`
Main Main `json:"main"`
Visibility int64 `json:"visibility"`
Wind Wind `json:"wind"`
Clouds Clouds `json:"clouds"`
Dt int64 `json:"dt"`
Sys Sys `json:"sys"`
Timezone int64 `json:"timezone"`
ID int64 `json:"id"`
Name string `json:"name"`
Cod int64 `json:"cod"`
}

type Clouds struct {
All int64 `json:"all"`
}

type Coord struct {
Lon float64 `json:"lon"`
Lat float64 `json:"lat"`
}

type Main struct {
Temp float64 `json:"temp"`
FeelsLike float64 `json:"feels_like"`
TempMin float64 `json:"temp_min"`
TempMax float64 `json:"temp_max"`
Pressure int64 `json:"pressure"`
Humidity int64 `json:"humidity"`
SeaLevel int64 `json:"sea_level"`
GrndLevel int64 `json:"grnd_level"`
}

type Sys struct {
Country string `json:"country"`
Sunrise int64 `json:"sunrise"`
Sunset int64 `json:"sunset"`
}

type WeatherElement struct {
ID int64 `json:"id"`
Main string `json:"main"`
Description string `json:"description"`
Icon string `json:"icon"`
}

type Wind struct {
Speed float64 `json:"speed"`
Deg int64 `json:"deg"`
Gust float64 `json:"gust"`
}

5.随机颜色生成器

随机uint8->随机rgb

package main

// import fyne
import (
"image/color"
"math/rand"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)

func main() {
// New app
a := app.New()
// Title and New window
w := a.NewWindow("Random Color Generator")
// Resize window
w.Resize(fyne.NewSize(400, 400))
// New Rectange
// Color for new Rectange
colorx := color.NRGBA{R: 0, G: 0, B: 0, A: 255}
rect1 := canvas.NewRectangle(colorx)
rect1.SetMinSize(fyne.NewSize(200, 200))
// Btn for color change
btn1 := widget.NewButton("Random color", func() {
// UI is done.. Now Logic
// unit8 is necessary to convert int to uint8
rect1.FillColor = color.NRGBA{R: uint8(rand.Intn(255)),
G: uint8(rand.Intn(255)), B: uint8(rand.Intn(255)), A: 255}
rect1.Refresh() // refresh screen
})
// Random RED Changer
btnRed := widget.NewButton("Random RED", func() {
// UI is done.. Now Logic
// unit8 is necessary to convert int to uint8
rect1.FillColor = color.NRGBA{R: uint8(rand.Intn(255)),
G: 0, B: 0, A: 255}
rect1.Refresh() // refresh screen
})
// Random GREEN COLOR
btnGreen := widget.NewButton("Random Green", func() {
// UI is done.. Now Logic
// unit8 is necessary to convert int to uint8
rect1.FillColor = color.NRGBA{R: 0,
G: uint8(rand.Intn(255)), B: 0, A: 255}
rect1.Refresh() // refresh screen
})
// Random Blue COLOR
btnBlue := widget.NewButton("Random Blue", func() {
// UI is done.. Now Logic
// unit8 is necessary to convert int to uint8
rect1.FillColor = color.NRGBA{R: 0,
G: 0, B: uint8(rand.Intn(255)), A: 255}
rect1.Refresh() // refresh screen
})
w.SetContent(
container.NewVBox(
rect1,
btn1,
btnRed,
btnGreen,
btnBlue,
),
)
w.ShowAndRun()
}

6.密码生成器

随机密码生成器,点击按钮生成指定位数的密码

package main  

import (
"fmt"
"image/color"
"math/rand"
"strconv"
"time"
// import fyne
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)

func main() {
// New App
a := app.New()
// New title and window
w := a.NewWindow("Password Generator")
// resize window
w.Resize(fyne.NewSize(400, 400))
title := canvas.NewText("Password Generator", color.Black)
// input Box
input := widget.NewEntry()
input.SetPlaceHolder("Enter password length")
//label to show password
text := canvas.NewText("", color.Black)
text.TextSize = 20
// button to generate password
btn1 := widget.NewButton("Generate", func() {
// input
passlength, _ := strconv.Atoi(input.Text) // convert string to integer
text.Text = PasswordGenerator(passlength)
text.Refresh()
})
// show content
w.SetContent(
container.NewVBox(
// put all widgets here
title,
input,
text,
btn1,
),
)
w.ShowAndRun()
// Fyne appp
}

// Converting the code to a function
func PasswordGenerator(passwordLength int) string {
// Password Generator
// Lower case
lowCase := "abcdefghijklmnopqrstuvxyz"
// Upper Case
upCase := "ABCDEFGHIJKLMNOPQRSTUVXYZ"
// Numbers
Numbers := "0123456789"
// Special characters
SpecialChar := "£$&()*+[]@#^-_!?"
// Password Length
// passwordLength := 8 // variable for storing password
password := ""
// loop
for n := 0; n < passwordLength; n++ {
// Now random characters
rand.Seed(time.Now().UnixNano())
randNum := rand.Intn(4)
fmt.Println(randNum)
// Switch statment
switch randNum {
case 0:
rand.Seed(time.Now().UnixNano())
randNum := rand.Intn(len(lowCase))
// len to find lenth of slice/array
// NOw we will store the generated passowrd character
password = password + string(lowCase[randNum])
// it is byte… we need string
// first case completed
case 1:
rand.Seed(time.Now().UnixNano())
randNum := rand.Intn(len(upCase))
// len to find lenth of slice/array
// NOw we will store the generated passowrd character
password = password + string(upCase[randNum])
// it is byte… we need string
// second done 🙂
case 2:
rand.Seed(time.Now().UnixNano())
randNum := rand.Intn(len(Numbers))
// len to find lenth of slice/array
// NOw we will store the generated passowrd character
password = password + string(Numbers[randNum])
// it is byte… we need string
// 3rd done 🙂
case 3:
rand.Seed(time.Now().UnixNano())
randNum := rand.Intn(len(SpecialChar))
// len to find lenth of slice/array
// NOw we will store the generated passowrd character
password = password + string(SpecialChar[randNum])
// it is byte… we need string
} // end of switch
} // end of for loop
fmt.Println(password)
// return password
return password
}

7.计算器样例

package main  

import (
"fmt"
"image/color"
"strconv"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget")

func main() {

a := app.New()
w := a.NewWindow("calc")
w.Resize(fyne.NewSize(400, 400))

var val1 int = 0
var val2 int = 0
var symbol string = ""
var total string = ""
var entryText string = ""

entry1 := widget.NewEntry()
entry1.TextStyle = fyne.TextStyle{Bold: true}
entry1.SetPlaceHolder("Calculator..")

btn1 := widget.NewButton("1", func() {
total = total + "1"
entryText = entryText + "1"
entry1.SetText(fmt.Sprint(entryText))
})
btn2 := widget.NewButton("2", func() {
total = total + "2"
entryText = entryText + "2"
entry1.SetText(fmt.Sprint(entryText))

})
btn3 := widget.NewButton("3", func() {
total = total + "3"
entryText = entryText + "3"
entry1.SetText(fmt.Sprint(entryText))

})
btn4 := widget.NewButton("4", func() {
total = total + "4"
entryText = entryText + "4"
entry1.SetText(fmt.Sprint(entryText))
})
btn5 := widget.NewButton("5", func() {
total = total + "5"
entryText = entryText + "5"
entry1.SetText(fmt.Sprint(entryText))
})
btn6 := widget.NewButton("6", func() {
total = total + "6"
entryText = entryText + "6"
entry1.SetText(fmt.Sprint(entryText))
})
btn7 := widget.NewButton("7", func() {
total = total + "7"
entryText = entryText + "7"
entry1.SetText(fmt.Sprint(entryText))
})
btn8 := widget.NewButton("8", func() {
total = total + "8"
entryText = entryText + "8"
entry1.SetText(fmt.Sprint(entryText))
})
btn9 := widget.NewButton("9", func() {
total = total + "9"
entryText = entryText + "9"
entry1.SetText(fmt.Sprint(entryText))
})
btn0 := widget.NewButton("0", func() {
total = total + "0"
entryText = entryText + "0"
entry1.SetText(fmt.Sprint(entryText))
})
btnDot := widget.NewButton(".", func() {

})

result := canvas.NewText("Result", color.Black)
result.TextSize = 30
result.Alignment = fyne.TextAlignCenter
btnClear := widget.NewButton("Clear", func() {
entry1.SetText("")
total = ""
result.Text = ""
entryText = ""
})
// btnClear.Text = "NoClear"
btnPlus := widget.NewButton("+", func() {
val1, _ = strconv.Atoi(total)
fmt.Print(fmt.Sprint(val1))
fmt.Print(fmt.Sprint(val2))
symbol = "+"
fmt.Print(symbol)

entryText = entryText + "+"
entry1.SetText(fmt.Sprint(entryText))
total = ""
})
btnMinus := widget.NewButton("-", func() {
val1, _ = strconv.Atoi(total)
fmt.Print(fmt.Sprint(val1))
fmt.Print(fmt.Sprint(val2))
symbol = "-"
fmt.Print(symbol)

total = ""
entryText = entryText + "-"
entry1.SetText(fmt.Sprint(entryText))

})
btnMultiply := widget.NewButton("x", func() {
val1, _ = strconv.Atoi(total)
fmt.Print(fmt.Sprint(val1))
fmt.Print(fmt.Sprint(val2))
symbol = "*"
fmt.Print(symbol)

total = ""

entryText = entryText + "*"
entry1.SetText(fmt.Sprint(entryText))
})
btnDivide := widget.NewButton("/", func() {
val1, _ = strconv.Atoi(total)
fmt.Print(fmt.Sprint(val1))
fmt.Print(fmt.Sprint(val2))
symbol = "/"
fmt.Print(symbol)

total = ""

entryText = entryText + "/"
entry1.SetText(fmt.Sprint(entryText))
})
btnEqual := widget.NewButton("=", func() {
val2, _ := strconv.Atoi(total)
if symbol == "+" {
myanswer := (val1) + (val2)
fmt.Println("Sum : ", myanswer)
result.Text = fmt.Sprint(myanswer)
result.Refresh()
} else if symbol == "-" {
myanswer := (val1) - (val2)
fmt.Println("Minus : ", myanswer)
result.Text = fmt.Sprint(myanswer)
result.Refresh()
} else if symbol == "*" {
myanswer := (val1) * (val2)
fmt.Println("Multiply : ", myanswer)
result.Text = fmt.Sprint(myanswer)
result.Refresh()
} else {
myanswer := (val1) / (val2)
fmt.Println("divide : ", myanswer)
result.Text = fmt.Sprint(myanswer)
result.Refresh()
}
total = ""
})

w.SetContent(
container.NewVBox(

entry1,
result,
container.NewGridWithColumns(
4,
btn1,
btn2,
btn3,
btn4,
btn5,
btn6,
btn7,
btn8,
btn9,
btn0,
btnDot,
btnEqual,
btnPlus,
btnMinus,
btnMultiply,
btnDivide,
btnClear,
),
),
)
w.ShowAndRun()
}

8.打开txt文件

package main

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/widget"
"io/ioutil"
)

func main() {
// New app
a := app.New()
//New title and window
w := a.NewWindow("Open file in FYNE")
// resize window
w.Resize(fyne.NewSize(400, 400))
// New Buttton
btn := widget.NewButton("Open .txt files", func() {
// Using dialogs to open files
// first argument func(fyne.URIReadCloser, error)
// 2nd is parent window in our case "w"
// r for reader
// _ is ignore error
file_Dialog := dialog.NewFileOpen(
func(r fyne.URIReadCloser, _ error) {
// read files
data, _ := ioutil.ReadAll(r)
// reader will read file and store data
// now result
result := fyne.NewStaticResource("name", data)
// lets display our data in label or entry
entry := widget.NewMultiLineEntry()
// string() function convert byte to string
entry.SetText(string(result.StaticContent))
// Lets show and setup content
// tile of our new window
w := fyne.CurrentApp().NewWindow(
string(result.StaticName)) // title/name
w.SetContent(container.NewScroll(entry))
w.Resize(fyne.NewSize(400, 400))
// show/display content
w.Show()
// we are almost done
}, w)
// fiter to open .txt files only
// array/slice of strings/extensions
file_Dialog.SetFilter(
storage.NewExtensionFileFilter([]string{".txt"}))
file_Dialog.Show()
// Show file selection dialog.
})
// lets show button in parent window
w.SetContent(container.NewVBox(
btn,
))
w.ShowAndRun()
}

9.手写txt保存到指定文件

手写txt文件后保存到指定文件中

package main

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/widget"
)

func main() {
// New app
a := app.New()
w := a.NewWindow("Save files...")
// file handling tutorial
// Resize
w.Resize(fyne.NewSize(400, 400))
// Entry to enter text
entry := widget.NewMultiLineEntry()
// btn to save text
btn := widget.NewButton("Save .txt file", func() {
// dialog
// 2 arguments
// one function
// 2nd parent window
fileDialog := dialog.NewFileSave(
// data of entry
// []byte() function is used to convert
// string to bytes slice
func(uc fyne.URIWriteCloser, _ error) {
data := []byte(entry.Text)
//_ to ignore error
// Lets write data
uc.Write(data)
}, w) // w is parent window
// File name(temporary)
fileDialog.SetFileName("anyFileName.txt")
// Show and setup
fileDialog.Show()
})
// show our two widgets on screen
w.SetContent(
container.NewVBox(
entry,
btn,
),
)
w.ShowAndRun()
}

10. 通过点击按钮查看选中的jpg文件

点击按钮查看选中的jpg文件

package main

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/widget"
"io/ioutil"
)

func main() {
// New app
a := app.New()
// New title
w := a.NewWindow("file Handling - Open Images")
//resize
w.Resize(fyne.NewSize(400, 400))
btn := widget.NewButton("Open .jpg & .Png", func() {
// dialog for opening files
// 2 arguments
fileDialog := dialog.NewFileOpen(
// _ to ignore error
func(uc fyne.URIReadCloser, _ error) {
// reader to read data
data, _ := ioutil.ReadAll(uc)
// static resource
// 2 arguments
// first is file name (string)
// second is data from reader
res := fyne.NewStaticResource(uc.URI().Name(), data)
// Now image widget to display our image
img := canvas.NewImageFromResource(res)
// setup new window for image and set content
w := fyne.CurrentApp().NewWindow(uc.URI().Name())
w.SetContent(img)
// resize window
w.Resize(fyne.NewSize(400, 400))
w.Show() // display our image
}, w)
// filtering files
fileDialog.SetFilter(
// filter jpg and png
// ignore rest of the files
storage.NewExtensionFileFilter([]string{".png", ".jpg"}))
fileDialog.Show()
// we are done :)
})
// display button in parent window
w.SetContent(btn)
w.ShowAndRun()
}

11.狗动画演示

package main

import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/widget"
"math/rand"
"time"
)

func main() {
a := app.New()
w := a.NewWindow("Dog And Cat Play")
x := float32(10)
y := float32(10)
rand.Seed(time.Now().UnixNano())
cx := float32(rand.Intn(400))
cy := float32(rand.Intn(400))
//窗口大小
w.Resize(fyne.NewSize(400, 400))
entry := widget.NewEntry()
entry.Resize(fyne.NewSize(200, 40))
entry.Move(fyne.NewPos(100, 100))
label := widget.NewLabel("Your selection")
label.Resize(fyne.NewSize(200, 70))
label.Move(fyne.NewPos(110, 60))
entry2 := widget.NewSelectEntry([]string{"Item 1", "Item 2"})
entry2.SetPlaceHolder("Select one or type")
entry2.Resize(fyne.NewSize(200, 40))
entry2.Move(fyne.NewPos(100, 180))

cat_img := canvas.NewImageFromURI(storage.NewFileURI("cat.png"))
cat_img.Resize(fyne.NewSize(100, 100))
cat_img.Move(fyne.NewPos(cx, cy))
// entry.OnChanged(x := entry2.Text)
dog_img := canvas.NewImageFromURI(storage.NewFileURI("dog.png"))
dog_img.Resize(fyne.NewSize(100, 100))
dog_img.Move(fyne.NewPos(100, 180))
down_btn := widget.NewButton("Down", func() {
// x = float32(x + 10)
n := float32(y + 10)
canvas.NewPositionAnimation(
fyne.NewPos(n, y),
fyne.NewPos(x, n),
canvas.DurationStandard,
func(p fyne.Position) {
dog_img.Move(p)
dog_img.Refresh()
}).Start()
//dog_img.Move(fyne.NewPos(x, y))
dog_img.Refresh()
y = n
})
// anim1 := canvas.NewPositionAnimation(
// fyne.NewPos(x, y),
// fyne.NewPos(x+10, y+10),
// canvas.DurationStandard,
// func(p fyne.Position) {
// dog_img.Move(p)
// dog_img.Refresh()
// })
up_btn2 := widget.NewButton("Up", func() {
// x = float32(x - 10)
n := float32(y - 10)
//n := float32(y + 10)
canvas.NewPositionAnimation(
fyne.NewPos(n, y),
fyne.NewPos(x, n),
canvas.DurationStandard,
func(p fyne.Position) {
dog_img.Move(p)
dog_img.Refresh()
}).Start()
//dog_img.Move(fyne.NewPos(x, y))
dog_img.Refresh()
//anim1.Start()
y = n
})
right_btn3 := widget.NewButton("Right", func() {
n := float32(x + 10)
// y = float32(y - 10)
//n := float32(y + 10)
canvas.NewPositionAnimation(
fyne.NewPos(x, n),
fyne.NewPos(n, y),
canvas.DurationStandard,
func(p fyne.Position) {
dog_img.Move(p)
dog_img.Refresh()
}).Start()
//dog_img.Move(fyne.NewPos(x, y))
dog_img.Refresh()
x = n
})
left_btn4 := widget.NewButton("Left", func() {
n := float32(x - 10)
// y = float32(y - 10)
//n := float32(y + 10)
canvas.NewPositionAnimation(
fyne.NewPos(x, n),
fyne.NewPos(n, y),
canvas.DurationStandard,
func(p fyne.Position) {
dog_img.Move(p)
dog_img.Refresh()
}).Start()
dog_img.Move(fyne.NewPos(x, y))
dog_img.Refresh()
x = n
})
down_btn.Resize(fyne.NewSize(50, 30))
down_btn.Move(fyne.NewPos(150, 60))
up_btn2.Resize(fyne.NewSize(50, 30))
up_btn2.Move(fyne.NewPos(150, 0))
right_btn3.Resize(fyne.NewSize(50, 30))
right_btn3.Move(fyne.NewPos(180, 30))
left_btn4.Resize(fyne.NewSize(50, 30))
left_btn4.Move(fyne.NewPos(130, 30))
w.SetContent(container.NewWithoutLayout(
dog_img, down_btn, up_btn2, right_btn3, left_btn4, cat_img,
))
w.ShowAndRun()
}

12.Crud 示例-学生记录管理

package main

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)

func main() {
// reading data from file
res, _ := ioutil.ReadFile("myfilename.txt")
// creating struct for my data
type Student struct {
Name string
Phone string
}
// slice/array to store all data
var mydata []Student
// parse json data
json.Unmarshal(res, &mydata)

a := app.New()
w := a.NewWindow("Student Record List")
w.Resize(fyne.NewSize(400, 400))
//创建List
list := widget.NewList(
func() int { return len(mydata) },
func() fyne.CanvasObject {
return widget.NewLabel("My list item widget")
},
func(lii widget.ListItemID, co fyne.CanvasObject) {
co.(*widget.Label).SetText(mydata[lii].Name)
},
)
label1 := widget.NewLabel("…")
label2 := widget.NewLabel("…")
//选中对应列表中的元素时,更新label1与label2
list.OnSelected = func(id widget.ListItemID) {
label1.Text = mydata[id].Name
label1.TextStyle = fyne.TextStyle{Bold: true}
label2.Text = mydata[id].Phone
// label2.TextStyle = fyne.TextStyle{Bold: true}
label1.Refresh()
label2.Refresh()
}
//输入框
e_name := widget.NewEntry()
e_name.SetPlaceHolder("Enter name …")
e_phone := widget.NewEntry()
e_phone.SetPlaceHolder("Enter phone …")
//按钮触发
e_submit := widget.NewButton("Submit", func() {
//两者内润存在,插入mydata并写入myfilename.txt
if e_name.Text != "" && e_phone.Text != "" {
obj1 := &Student{
Name: e_name.Text,
Phone: e_phone.Text,
}
mydata = append(mydata, *obj1)
b, _ := json.MarshalIndent(mydata, "", " ")
os.WriteFile("myfilename.txt", b, 0644)
e_name.Text = ""
e_phone.Text = ""
e_name.Refresh()
e_phone.Refresh()
//其余情况提示输入有误
} else {
label1.Text = "Incorrect data"
label2.Text = ""
label2.Refresh()
label1.Refresh()
}
list.Refresh()
})
//删除按钮
e_del := widget.NewButton("DELETE", func() {
var mydata2 []Student
//与当前label1值一样的被去除
for _, a := range mydata {
if a.Name != label1.Text {
mydata2 = append(mydata2, a)
fmt.Println(a)
}
}
//更新mydata与myfilename.txt
mydata = mydata2
b, _ := json.MarshalIndent(mydata2, "", " ")
os.WriteFile("myfilename.txt", b, 0644)
e_name.Text = ""
e_phone.Text = ""
e_name.Refresh()
e_phone.Refresh()
list.Refresh()
})
//更新按钮
e_update := widget.NewButton("Update", func() {
//输入内容均存在
if e_name.Text != "" && e_phone.Text != "" {
var mydata2 []Student
for _, a := range mydata {
//不是更改的数据就直接放回data
if a.Name != label1.Text {
mydata2 = append(mydata2, a)
fmt.Println(a)
} else {
//更改的数据经过重新赋值放回data
obj1 := &Student{
Name: e_name.Text,
Phone: e_phone.Text,
}
mydata2 = append(mydata2, *obj1)
fmt.Println(a)
}
}
mydata = mydata2
b, _ := json.MarshalIndent(mydata2, "", " ")
os.WriteFile("myfilename.txt", b, 0644)
e_name.Text = ""
e_phone.Text = ""
e_name.Refresh()
e_phone.Refresh()
list.Refresh()
//其他情况提示布局有误
} else {
label1.Text = "Incorrect data"
label2.Text = ""
label2.Refresh()
label1.Refresh()
}
list.Refresh()
})
//布局
c := container.NewVBox(label1, label2,
e_name, e_phone, e_submit, e_del, e_update)
w.SetContent(container.NewHSplit(
list,
c,
))
w.ShowAndRun()
fmt.Println(mydata)
}

13.QR-Code生成器

package main

// import fyne
import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
"github.com/skip2/go-qrcode"
"strconv"
)

func main() {
// new app
a := app.New()
// title & window
w := a.NewWindow("Qr code Generator")
// resize
w.Resize(fyne.NewSize(400, 400))
// qrcode generator
url := widget.NewEntry()
url.SetPlaceHolder("Enter url ...")
size := widget.NewEntry()
size.SetPlaceHolder("Enter file size i.e 256 ...")
size_1, _ := strconv.Atoi(size.Text)
file_name := widget.NewEntry()
file_name.SetPlaceHolder("Enter file name ...")
btn := widget.NewButton("Create", func() {
// we are going to use qrcode lib
// go get -u github.com/skip2/go-qrcode/
// install and use
// file content
// quality / resolution
// size of image 256x256
err1 := qrcode.WriteFile(
url.Text,
qrcode.Highest,
size_1,
fmt.Sprintf("%s.png", file_name.Text),
// sprintf will add add suffix .png
)
if err1 != nil {
fmt.Println(err1)
}
})
w.SetContent(container.NewVBox(
url,
size,
file_name,
btn,
))
w.ShowAndRun()
}

14. 音乐播放器

音乐播放包

package main

import (
"github.com/faiface/beep/mp3"
"github.com/faiface/beep/speaker"
"os"
"time"
)

func main() {
// open file
// underscore mean we are ignoring error
f, _ := os.Open("hen.mp3")
// decoding mp3 file
// 3 outputs
// stream , format and error
streamer, format, _ := mp3.Decode(f)
// activate speakers
speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
// play
speaker.Play(streamer)
// looping
select {}
}

音乐播放器demo

package main

import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"github.com/faiface/beep"
"github.com/faiface/beep/mp3"
"github.com/faiface/beep/speaker"
"os"
"time"
)

var f *os.File
var format beep.Format
var streamer beep.StreamSeekCloser
var pause bool = false

func main() {
go func(msg string) {
fmt.Println(msg)
if streamer == nil {
} else {
//slider.Value = float64(streamer.Position())
fmt.Println(fmt.Sprint(streamer.Len()))
}
}("going")
time.Sleep(time.Second)
a := app.New()
w := a.NewWindow("audio player...")
w.Resize(fyne.NewSize(400, 400))
logo := canvas.NewImageFromFile("cat.png")
logo.FillMode = canvas.ImageFillOriginal
toolbar := widget.NewToolbar(
widget.NewToolbarSpacer(),
widget.NewToolbarAction(theme.MediaPlayIcon(), func() {
// f, _ = os.Open("hen.mp3")
speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
speaker.Play(streamer)
}),
widget.NewToolbarAction(theme.MediaPauseIcon(), func() {
if !pause {
pause = true
speaker.Lock()
} else if pause {
pause = false
speaker.Unlock()
}
}),
widget.NewToolbarAction(theme.MediaStopIcon(), func() {
speaker.Clear()
// speaker.Close()
}),
widget.NewToolbarSpacer(),
)
label := widget.NewLabel("Audio MP3..")
label.Alignment = fyne.TextAlignCenter
label2 := widget.NewLabel("Play MP3..")
label2.Alignment = fyne.TextAlignCenter
browse_files := widget.NewButton("Browse...", func() {
fd := dialog.NewFileOpen(func(uc fyne.URIReadCloser, _ error) {
streamer, format, _ = mp3.Decode(uc)
label2.Text = uc.URI().Name()
label2.Refresh()
}, w)
fd.Show()
fd.SetFilter(storage.NewExtensionFileFilter([]string{".mp3"}))
})
// slider := widget.NewSlider(0, 100)
c := container.NewVBox(label, browse_files, label2, toolbar)
w.SetContent(
container.NewBorder(logo, nil, nil, nil, c),
)
w.ShowAndRun()
}

15. Notepad Demo

package main

import (
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/widget"
"io/ioutil"
"os"
"strconv"
)

var count int = 1
var filepath string

func main() {
a := app.New()
w := a.NewWindow("Fyne Note Pad")
input := widget.NewMultiLineEntry()
input.SetPlaceHolder("Enter text...")
input.Move(fyne.NewPos(0, 0))
input.Resize(fyne.NewSize(500, 500))
new1 := fyne.NewMenuItem("New", func() {
filepath = ""
w.SetTitle("Fyne Note Pad")
input.Text = ""
input.Refresh()
})
save1 := fyne.NewMenuItem("Save", func() {
if filepath != "" {
f, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
//handle error
}
defer f.Close()
//f.Write([]byte(input.Text))
f.WriteString(input.Text)
} else {
saveFileDialog := dialog.NewFileSave(
func(r fyne.URIWriteCloser, _ error) {
textData := []byte(input.Text)
r.Write(textData)
filepath = r.URI().Path()
w.SetTitle(filepath)
}, w)
saveFileDialog.SetFileName("New File" + strconv.Itoa(count-1) + ".txt")
saveFileDialog.Show()
}
})
saveAs1 := fyne.NewMenuItem("Save as..", func() {
saveFileDialog := dialog.NewFileSave(
func(r fyne.URIWriteCloser, _ error) {
textData := []byte(input.Text)
r.Write(textData)
filepath = r.URI().Path()
w.SetTitle(filepath)
}, w)
saveFileDialog.SetFileName("New File" + strconv.Itoa(count-1) + ".txt")
saveFileDialog.Show()
})
open1 := fyne.NewMenuItem("Open", func() {
openfileDialog := dialog.NewFileOpen(
func(r fyne.URIReadCloser, _ error) {
data, _ := ioutil.ReadAll(r)
result := fyne.NewStaticResource("name", data)
input.SetText(string(result.StaticContent))
fmt.Println(result.StaticName + r.URI().Path())
filepath = r.URI().Path()
w.SetTitle(filepath)
}, w)
openfileDialog.SetFilter(
storage.NewExtensionFileFilter([]string{".txt"}))
openfileDialog.Show()
})
menuItem := fyne.NewMenu("File", new1, save1, saveAs1, open1)
menux1 := fyne.NewMainMenu(menuItem)
w.SetMainMenu(menux1)
w.SetContent(
container.NewWithoutLayout(
input,
),
)
w.Resize(fyne.NewSize(500, 500))
w.ShowAndRun()
}

16.图像透明度

package main

// import fyne
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
)

func main() {
// new app
a := app.New()
// new window
w := a.NewWindow("Image Translucency-Alpha")
w.Resize(fyne.NewSize(400, 400))
img := canvas.NewImageFromFile("bg.jpg")
img.Translucency = 0.9 // you can use 0.1 to 0.99
// set content
w.SetContent(img) // we will create image variable
w.ShowAndRun()
}

17.其余项目

电子邮件提取系统: https://blogvali.com/email-extract-app-fyne-golang-gui-tutorial-72/
URL缩短器:https://blogvali.com/url-shortner-fyne-golang-gui-tutorial-73/
加密货币更新:https://blogvali.com/cryptocurrency-updates-fyne-golang-gui-tutorial-74/
发送电子邮件GUI客户端:https://blogvali.com/sending-email-gui-client-fyne-golang-coding-tutorial/

6.问题解决

1.中文乱码

go get -u "github.com/flopp/go-findfont"

加上下面的代码即可

func init() {
//设置中文字体:解决中文乱码问题
fontPaths := findfont.List()
for _, path := range fontPaths {
if strings.Contains(path, "msyh.ttf") || strings.Contains(path, "simhei.ttf") || strings.Contains(path, "simsun.ttc") || strings.Contains(path, "simkai.ttf") {
os.Setenv("FYNE_FONT", path)
break
}
}
}

2.Table

我想设置一个类似于常见webshell管理工具那种表格,
https://git.sr.ht/~uid/flextable
可以选中整行,看源码可以自己改颜色

测试样例:

package main  

import (
"fmt"
"strconv"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"git.sr.ht/~uid/flextable"
)

func GetTableData() *flextable.TableData {
data := flextable.NewTableData("MyTable")
for i := 0; i < 5; i++ {
header := "Header - " + strconv.Itoa(i)
for j := 0; j < 20; j++ {
data.AddStringCell(header, strconv.Itoa(j)+
" some long text to illustrate how that looks")
}
}
return data
}

func main() {
app := app.New()
window := app.NewWindow("Flextable Example")

data := GetTableData()

table := flextable.NewTable(data, func(c *flextable.TableCell) {
fmt.Printf("I have been tapped. Cell value %s, Row: %d, Column name: %s\n",
c.Text(), c.Id.Row, c.ColumnName())
})

window.SetContent(table)
window.Resize(fyne.NewSize(1000, 600))

window.ShowAndRun()
}

其中的每一列都可以单独调整宽度

基础样式更改

func NewTable(data *TableData, onClick func(cell *TableCell)) *Table {  
table := &Table{
onClick: onClick,
selectedRow: -1,
minWidth: float32(data.ColumnCount() * 200),
//选中时颜色
SelectionColor: color.RGBA{0, 85, 255, 255},
CellBgColor: theme.BackgroundColor(),
//头颜色
headerBgColor: color.RGBA{89, 89, 89, 255},
}