GUI development with Fyne by Go

Of course, GUI development is more complicated to create than a command line application. Fyne chose Fyne for the time being because he said he would use Go's excellent design to make building a GUI simple and quick. Eventually, I want to be able to use Go-made shiny. So, I want to migrate the following programs to GUI.

CSV file summary Go program for Resona IB Go program to manage save data of minecraft

With that said, I didn't plan to participate in the Advent calendar, but I decided to post it in a hurry because there was a frame. (Although it's in the vacancy, I don't like the feeling of being delayed ... I think I forgot to post ... sad)

How to get (environment construction)

You can use it with the following commands.

console


go get fyne.io/fyne

The above command completes the environment construction. Below are the demo settings

console


go get fyne.io/fyne/cmd/fyne_demo
fyne_demo

The following is the screen immediately after starting the demo.

demo.jpg

You can try most objects.

Hello World First of all, the basics.

Sample code


package main

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

func main() {
	myApp := app.New()
	myWindow := myApp.NewWindow("Hello")	//Window title

	myWindow.SetContent(widget.NewLabel("Hello World!"))	//Place text labels on window content

	myWindow.ShowAndRun()	//Run application(Show & Run)
	//If the process is described after this point, it will not be executed until the application finishes executing.
}

1.jpg

Fyne package structure

The packages are separated according to the type of type.

fyne.io/fyne Providing a basic definition common to all Fyne codes. Includes data types and interfaces.

fyne.io/fyne/app Provide an API to launch a new application. Normally, you only need app.New ().

fyne.io/fyne/canvas Provides all drawing APIs in Fyne. The complete Fyne toolkit consists of these basic graphical types (simple canvas).

fyne.io/fyne/dialog Dialog windows such as confirmations and errors are handled by this package.

fyne.io/fyne/layout Provides a variety of layout implementations. Containers are available.

fyne.io/fyne/test This package makes it easier to test your application.

fyne.io/fyne/widget This package provides a variety of widget collections. Interactions with widgets are also provided in this package.

Other

Other features

I'm not sure, but I'll give you a glimpse of what I think I understood.

Cross compiler

Icons and metadata are associated with each OS, and the format required for those environments is required. The finy command can handle the complicated environment if the OS is supported by the toolkit.

By executing "fyne package", will applications with different installation formats be generated for each OS ... (I don't understand).

In the case of WindowsOS, an exe file with an icon is created. For MacOS, generate an app bundle. For Linux, create a tar.xz file.

console


go get fyne.io/fyne/cmd/fyne

go build
fyne package -icon mylogo.png

Unfortunately I couldn't do it in my environment (maybe I need to go through Path).

Details of the above sample code

In order for the GUI to start up, a run loop (Runloop / event loop) that handles drawing events is essential. In Fyne, use Window.ShowAndRun () or App.Run (). It also needs to be called at the end of the main () function (see sample code). Note that if you call it in the middle of processing, the subsequent processing will not be executed until the window is closed.

This runloop can only be run once within an application, so multiple runs will result in an error (one call is required).

Sample code


func main() {
	myApp := app.New()
	myWindow := myApp.NewWindow("Hello")
	myWindow.SetContent(widget.NewLabel("Hello"))

	myWindow.Show()	//Window display
	myApp.Run()	//Window execution
	tidyUp()	//Executed after the window is closed.
}

func tidyUp() {
	//A function that is called after the GUI window is closed.
	fmt.Println("Exited")
}

You can terminate the application by executing App.Quit () on the code. However, it is necessary to use it in the call from the user (the usual x button at the top of the window) because an unexpected event occurs by issuing the end instruction directly from the source code.

Further details

The window is created using App.NewWindow () and displayed by the Show () function.

Excerpt


	myApp := app.New()
	myWindow := myApp.NewWindow("Hello")	//Window generation
・
・
・
	myWindow.Show()	//Window display
	myApp.Run()	//Window execution

As shown in the sample code above, the ShowAndRun () function can be used to execute both Show and Run. This ShowAndRun function is one of the helper methods in fine.Window.

Excerpt


	myApp := app.New()
	myWindow := myApp.NewWindow("Hello")	//Window generation
・
・
・
	myWindow.ShowAndRun()	//Window display and execution

If you want to create a child window, you only need to call the Show () function (which you can do with the Goroutine function callee).

Goroutine function

The following explanations require knowledge of goroutine (concurrency).

About canvas

In Fyne, Canvas is where the application is drawn. Each window is drawn with Window.Canvas (), but it can be omitted. In the first place, anything that can be drawn with Fyne is a type of CanvasObject.

Sample code


func main() {
	myApp := app.New()
	myWindow := myApp.NewWindow("Canvas") //Window title
	myCanvas := myWindow.Canvas()         //Canvas generation

	text := canvas.NewText("Text", color.Black) //Black letters ready on canvas
	text.TextStyle.Bold = true                  //Bold
	myCanvas.SetContent(text)                   //Text drawing above
	go changeContent(myApp, myCanvas)           //Goroutine function call

	myWindow.Resize(fyne.NewSize(200, 100))
	myWindow.ShowAndRun()
}

func changeContent(a fyne.App, c fyne.Canvas) {
	time.Sleep(time.Second * 2)

	c.SetContent(canvas.NewRectangle(color.Black)) //Fill the canvas with black(Rectangle fixed)。

	time.Sleep(time.Second * 2)
	c.SetContent(canvas.NewLine(color.Gray{0x66})) //Draw a line on the canvas

	win := a.NewWindow("Child window")
	win.SetContent(widget.NewLabel("5 seconds later"))
	win.Resize(fyne.NewSize(200, 200))
	circle := canvas.NewCircle(color.Black) //Circular on canvas(Fill with black)
	circle.StrokeWidth = 8
	circle.StrokeColor = color.RGBA{0x00, 0x00, 0xFF, 0x00} //The circular line is blue
	win.SetContent(circle)
	win.Show() //Child window display
	time.Sleep(time.Second * 2)
	win.Hide() //Hide child window

	time.Sleep(time.Second * 2)
	c.SetContent(canvas.NewImageFromResource(theme.FyneLogo())) //Logo display
}

child.jpg

It seems that it can be redrawn? canvas.Refresh(circle) However, I could not tell the difference before and after use.

canvas.NewLine draws a line from top left to bottom right by default.

I'm worried that the process of displaying the child window is correct. Also, external packages introduced from github do not complement and are very inconvenient.

MSCode.jpg

I think it is unique to MSCode, but I want you to eliminate it.

About multiple canvases

Only one of the above was used. However, that is not enough for actual operation. To use multiple canvases, use containers together.

Sample code


func main() {
	myApp := app.New()
	myWindow := myApp.NewWindow("Container")

	text1 := canvas.NewText("Hello", color.Black)	//Creating a text object
	text2 := canvas.NewText("There", color.Black)	//Creating a text object
	text2.Move(fyne.NewPos(20, 20))					//Moving the second text object
	text3 := canvas.NewText("World", color.Black)	//Creating a text object
	container := fyne.NewContainer(text1, text2, text3)	//Place three text objects in a container.

	myWindow.SetContent(container)	//Set the above container as content in the window
	myWindow.ShowAndRun()	//Display and execute windows.
}

Of course, the container is also part of the canvas object, so it can be set as the canvas content. procedure

  1. Creating a text object
  2. Do it 3 times.
  3. Move the second text object (text2).
  4. Place three text objects in a container.

It becomes a flow to say.

2.jpg

I'm moving objects because I'm not using a layout set. In short, text1 and text3 that have not been moved are covered. Below is the grid layout.

container := fyne.NewContainerWithLayout(layout.NewGridLayout(2), text1, text2, text3)

Below is the grid wrap layout.

layout.NewGridWrapLayout(fyne.NewSize(50, 50))

Below is the borderline layout. The four arguments are the location. Specify nil if it is not required.

layout.NewBorderLayout(top, bottom, left, right)

fyne.Layout implements methods for organizing items in a container. Modify the container to use a two-column grid layout. By resizing the window, you can see that the text changes depending on the layout. Also make sure that the manually modified code in text2 is ignored.

3.jpg

Widget

fyne.Widget becomes a special type of container (it seems to have additional logic associated with it, but it doesn't make sense). (It seems to be called Widget Renderer). I'm not sure, but widgets are also part of the canvas object.

Add widget.Entry to the window content (only one example below). To add multiple widgets, use a set of widgets instead of a container.

Sample code


func main() {
	myApp := app.New()
	myWindow := myApp.NewWindow("Widget")

	myWindow.SetContent(widget.NewEntry())
	myWindow.ShowAndRun()
}

In this widget, it is a box where you can enter characters, but you cannot enter multiple bytes.

4.jpg

However, if it is a solid writing in the source code, it can be displayed. I wonder if I'm in trouble for now ...

For the time being, it seems that Japanese can be displayed by specifying the font in the environment variable FYNE_FONT.

Reference URL

Oomoto (?) Fyne site package fyne Cross-platform GUI application development starting with Go UI toolkit Fyne

version

It seems that 1.4 is used this time.

that's all.

Recommended Posts

GUI development with Fyne by Go
Python with Go
Go (Echo) Go Modules × Build development environment with Docker
Development digest with Django
Install Ubuntu 20.04 with GUI and prepare the development environment
Build a Go development environment with VS Code's Remote Containers
Create a GO development environment with [Mac OS Big Sur]
Do embedded programming by test-driven development with google test-SOLID design-
Draw Bezier curves with Go
Operate Db2 container with Go
Getting Started with Go Assembly
Creating GUI tools with pyinstaller
Bit full search with Go
Web application development with Flask
Connect to Postgresql with GO
Hot reload with Go + Air
[GUI with Python] PyQt5-Layout management-
Standardize by group with pandas
Try implementing perfume with Go
[GUI with Python] PyQt5 -Preparation-
[GUI with Python] PyQt5 -Paint-
Create a development environment for Go + MySQL + nginx with Docker (docker-compose)