📜 ⬆️ ⬇️

Go GUI Notepad

Despite the fact that the Go language has existed for more than one year, there is almost no information on how to create GUI applications in this language. Perhaps this is due to the fact that among the official libraries there is still no library to work with the GUI. However, this does not mean that we cannot create an application with a user interface: there are libraries that provide this feature. I will give them a list . But there are several other libraries not listed in this list. Among them - Walk , whose name stands for “Windows Application Library Kit”. With it, I will try to create a small application with a user interface.

Formulation of the problem

Suppose I want to create a small notepad that allows me to save the entered text to a file, load this text back, copy the text to the clipboard, and extract from it.

Installing the Walk Library

Walk only works with Go version 1.1.x and higher. At the first stage, you need to download and install the library from GitHub. Run the CMD and execute the command:
go get github.com/lxn/walk 

If Go swears and gives something like:
 go: missing Git command ... 
You need to visit git-scm.com/downloads and install Git. If after installation its error did not disappear, you need to make sure that the path to Git is registered in% PATH%.

Creating a blank form

Create the original gopad.go file with the following contents:
 package main import ( . "github.com/lxn/walk/declarative" ) func main() { MainWindow{ Title: "GoPad", //    MinSize: Size{600, 400}, //     }.Run() } 

Now let's compile our source. Create a build.bat bat script with the following contents:
 go build -ldflags="-H windowsgui" pause 

We could not prescribe the ldflags key, but then the form would run along with the console in the background. Run our script and make sure that everything compiled correctly. But it is too early to launch the resulting .exe file. We need to create another file - manifest. Create a file gopad.exe.manifest (instead of gopad.exe should be the name of the resulting binary) with the following contents:
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="SomeName" type="win32"/> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/> </dependentAssembly> </dependency> </assembly> 

The manifesto must be present. Without it, the binary will not start!
When done, it's time to run our empty form to make sure everything works. I got the program looks like this:

')
Add the necessary buttons and input field

To begin, add an input field. Add another library to the import:
 import ( "github.com/lxn/walk" . "github.com/lxn/walk/declarative" ) 

Then create an input field, a pointer variable, and bind it to the field:
 func main() { var edit *walk.TextEdit MainWindow{ Title: "GoPad", MinSize: Size{600, 400}, Layout: VBox{}, Children: []Widget{ TextEdit{AssignTo: &edit}, }, }.Run() } 

Run and make sure that the input field appears, which is displayed on the entire form.
In the same way, we will write four buttons in MainWindow: “Copy”, “Paste”, “Load”, “Save”:
 MainWindow{ Title: "GoPad", MinSize: Size{600, 400}, Layout: VBox{}, Children: []Widget{ TextEdit{AssignTo: &edit}, HSplitter{ MinSize: Size{600, 30}, Children: []Widget{ PushButton{ Text: "Copy", }, PushButton{ Text: "Paste", }, PushButton{ Text: "Load", }, PushButton{ Text: "Save", }, }, }, }, }.Run() 

As a result, we get the following form:

When all the elements are located on it, it's time to add some functionality.

Work with buffer

To add a button click handler, just write the necessary function, which will be launched when the button is clicked, in the properties of the button itself:
 PushButton{ Text: "Save", OnClicked: func() { // ... }, }, 

We can either create an anonymous function, or register an existing one.

Walk allows us to work with the clipboard directly through these functions:
 walk.Clipboard().SetText("text"); //      walk.Clipboard().Text(); //   

To get or replace text in the input field, use the following functions:
 edit.Text(); //      edit.SetText("text"); //      

Now the contents of our buttons will be like this:
 PushButton{ Text: "Copy", OnClicked: func() { walk.Clipboard().SetText(edit.Text()); }, }, PushButton{ Text: "Paste", OnClicked: func() { if text, err := walk.Clipboard().Text(); err == nil { edit.SetText(text) } }, }, 


Save to file and load from it

Let's load and save to a file in separate functions. To do this, we make the edit variable global. Let's create the readFromFile function that loads text from the text file file.txt into the field (do not forget that in the import you need to add "io/ioutil" ):
 var edit *walk.TextEdit func readFromFile() { contents,_ := ioutil.ReadFile("file.txt") edit.SetText(string(contents)) } 

Similarly, let's save to a file:
 func saveToFile() { ioutil.WriteFile("file.txt", []byte(edit.Text()), 0x777) } 

Now we need to bind the functions to the corresponding buttons:
 PushButton{ Text: "Load", OnClicked: readFromFile, }, PushButton{ Text: "Save", OnClicked: saveToFile, }, 

PS The program reads and writes the contents of a text file in Unicode.

Results

We created a small notebook with a GUI in Go language using the Walk library. If desired, the functionality can be expanded: add file selection, context menu, work with tabs and fonts and much more. Walk is actively developing and provides access to a large number of WinUI components. There are many examples using the library.

Source codes of files:

gopad.go
 package main import ( "github.com/lxn/walk" . "github.com/lxn/walk/declarative" "io/ioutil" ) var edit *walk.TextEdit func readFromFile() { contents,_ := ioutil.ReadFile("file.txt") edit.SetText(string(contents)) } func saveToFile() { ioutil.WriteFile("file.txt", []byte(edit.Text()), 0x777) } func main() { MainWindow{ Title: "GoPad", MinSize: Size{600, 400}, Layout: VBox{}, Children: []Widget{ TextEdit{AssignTo: &edit}, HSplitter{ MaxSize: Size{600, 30}, Children: []Widget{ PushButton{ Text: "Copy", OnClicked: func() { walk.Clipboard().SetText(edit.Text()); }, }, PushButton{ Text: "Paste", OnClicked: func() { if text, err := walk.Clipboard().Text(); err == nil { edit.SetText(text) } }, }, PushButton{ Text: "Load", OnClicked: readFromFile, }, PushButton{ Text: "Save", OnClicked: saveToFile, }, }, }, }, }.Run() } 

gopad.exe.manifest
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="SomeFunkyNameHere" type="win32"/> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/> </dependentAssembly> </dependency> </assembly> 

build.bat
 go build -ldflags="-H windowsgui" pause 


Links

Source: https://habr.com/ru/post/205268/


All Articles