GO没有原生的界面库,所以不能直接用来写GUI界面。但最近互联网上已经涌现出不少成熟、好用的第三方界面库。使用它们,就同样可以写出同C#、C++的界面。而且效率还更胜一筹。
关于Walk界面库(官方介绍):Walk是一个写给Golang的Window应用程序库套件,它主要用于桌面GUI的开发,但也有更多的东西。
在浏览这部分前,请确定已经配置安装完毕go语言的环境。如果没有,可以参考go官网的Install帮助。另外,注意:这个Walk库只能运行在Go 1.1.x及以上。
要安装Walk很简单,只要运行命令:go get github.com/lxn/walk
等待命令执行完毕,这时候检查GOPATH的src与pkg下,是否有符合自己计算机环境的walk目录。(我的电脑的CPU架构为AMD64,则会在%GOPATH%\windows_amd64\github.com\lxn
下出现一个walk文件夹与编译完成的a文件,另外在%GOPATH%\src\github.com\lxn
下也会出现walk的源代码)
我们还要安装一个工具rsrc,以完成后期的打包工作,执行命令:go get github.com/akavel/rsrc
等待命令执行完成,然后检查,步骤与上文相仿,不再多说。
导入依赖
import (
//引入walk包
"github.com/lxn/walk"
//declarative包下包含大量控件,加一个点:使用包内的成员时可以省略包名
."github.com/lxn/walk/declarative"
"strings"
)
func main() {
//声明两个文本域控件
var inTE, outTE *walk.TextEdit
//配置主窗口,并运行起来
MainWindow{
//窗口标题
Title: "尖叫的Demo",
//可拉伸的最小尺寸
MinSize: Size{600, 400},
//主布局:垂直布局
Layout: VBox{},
//窗口中的所有控件
Children: []Widget{
//水平分割器(水平小布局)
HSplitter{
//局部水平排列的控件们
Children: []Widget{
//文本输入框
TextEdit{
//绑定到inTE变量
AssignTo: &inTE},
//文本输出框
TextEdit{
AssignTo: &outTE,
//只读的文本框
ReadOnly: true},
},
},
//普通按钮
PushButton{
//按钮文本
Text: "动动我试试",
//响应函数
OnClicked: func() {
inputStr := inTE.Text()
outputStr := strings.ToUpper(inputStr)
outTE.SetText(outputStr)
},
},
},
}.Run()
}
认识几种常用控件
导入依赖
import (
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
"os"
"strings"
"io/ioutil"
"fmt"
"log"
)
定义全局数据
// 全局应用的菜单项
var myAction *walk.Action
//自定义的主窗口
var myWindow *MyMainWindow
//自定义窗口
type MyMainWindow struct {
*walk.MainWindow
te *walk.TextEdit
//listbox使用的数据
model *EnvModel
//listbox控件
listBox *walk.ListBox
}
定义列表数据模型
//环境变量条目数据模型
type EnvItem struct {
//环境变量的名字和值
name string
value string
}
//列表数据模型
type EnvModel struct {
//继承ListModelBase
walk.ListModelBase
//环境变量数集合
items []EnvItem
}
//列表数据模型的工厂方法
func NewEnvModel() *EnvModel {
env := os.Environ()
m := &EnvModel{items: make([]EnvItem, len(env))}
for i, e := range env {
j := strings.Index(e, "=")
if j == 0 {
continue
}
name := e[0:j]
value := strings.Replace(e[j+1:], ";", "\r\n", -1)
m.items[i] = EnvItem{name, value}
}
return m
}
定义列表相关的监听和系统回调接口
//定义列表项目的单击监听
func (mw *MyMainWindow) lb_CurrentIndexChanged() {
i := mw.listBox.CurrentIndex()
item := &mw.model.items[i]
mw.te.SetText(item.value)
fmt.Println("CurrentIndex: ", i)
fmt.Println("CurrentEnvVarName: ", item.name)
}
//定义列表项目的双击监听
func (mw *MyMainWindow) lb_ItemActivated() {
value := mw.model.items[mw.listBox.CurrentIndex()].value
walk.MsgBox(mw, "Value", value, walk.MsgBoxIconInformation)
}
//列表的系统回调方法:获得listbox的数据长度
func (m *EnvModel) ItemCount() int {
return len(m.items)
}
//列表的系统回调方法:根据序号获得数据
func (m *EnvModel) Value(index int) interface{} {
return m.items[index].name
}
定义普通事件回调
//显示消息窗口
func ShowMsgBox(title, msg string) int {
return walk.MsgBox(myWindow, "天降惊喜", "你老婆跟人跑了!", walk.MsgBoxOK)
}
//一个普通的事件回调函数
func TiggerFunc() {
ShowMsgBox("天降惊喜", "你老婆跟人跑了!")
}
主调函数
func main() {
defer func() {
if err := recover(); err != nil {
errMsg := fmt.Sprintf("%#v", err)
ioutil.WriteFile("fuck.log", []byte(errMsg), 0644)
}
}()
myWindow = &MyMainWindow{model: NewEnvModel()}
if _, err := (MainWindow{
AssignTo: &myWindow.MainWindow,
Title: "常用控件",
//窗口菜单
MenuItems: []MenuItem{
//主菜单一
Menu{
Text: "川菜",
//菜单项
Items: []MenuItem{
//菜单项一
Action{
AssignTo: &myAction,
Text: "鱼香肉丝",
//菜单图片
Image: "img/open.png",
//快捷键
Shortcut: Shortcut{walk.ModControl, walk.KeyO},
OnTriggered: func() {
ShowMsgBox("已下单", "我是菜单项")
},
},
//分隔线
Separator{},
//菜单项二
Action{
//文本
Text: "水煮鱼",
//响应函数
OnTriggered: func() {
ShowMsgBox("已下单", "您要的菜马上就去买")
},
},
},
},
//主菜单二
Menu{
Text: "粤菜",
//菜单项
Items: []MenuItem{
//菜单项一
Action{
Text: "鱼香肉丝",
//菜单图片
Image: "img/open.png",
//快捷键
Shortcut: Shortcut{walk.ModControl, walk.KeyO},
OnTriggered: func() {
ShowMsgBox("已下单", "我是菜单项")
},
},
//分隔线
Separator{},
//菜单项二
Action{
//文本
Text: "水煮鱼",
//响应函数
OnTriggered: func() {
ShowMsgBox("已下单", "您要的菜马上就去买")
},
},
},
},
},
//工具栏
ToolBar: ToolBar{
//按钮风格:图片在字的前面
ButtonStyle: ToolBarButtonImageBeforeText,
//工具栏中的工具按钮
Items: []MenuItem{
//引用现成的Action
ActionRef{&myAction},
Separator{},
//自带子菜单的工具按钮
Menu{
//工具按钮本身的图文和监听
Text: "工具按钮2",
Image: "img/document-properties.png",
OnTriggered: TiggerFunc,
//附带一个子菜单
Items: []MenuItem{
Action{
Text: "X",
OnTriggered: TiggerFunc,
},
Action{
Text: "Y",
OnTriggered: TiggerFunc,
},
Action{
Text: "Z",
OnTriggered: TiggerFunc,
},
},
},
Separator{},
//普通工具按钮
Action{
Text: "工具按钮3",
Image: "img/system-shutdown.png",
OnTriggered: func() {
ShowMsgBox("天降惊喜", "你老婆跟人跑了!")
},
},
},
},
MinSize: Size{600, 400},
Layout: VBox{},
//控件们
Children: []Widget{
//水平局部
HSplitter{
MinSize: Size{600, 300},
Children: []Widget{
ListBox{
StretchFactor: 1,
//赋值给myWindow.listBox
AssignTo: &myWindow.listBox,
//要显示的数据
Model: myWindow.model,
//单击监听
OnCurrentIndexChanged: myWindow.lb_CurrentIndexChanged,
//双击监听
OnItemActivated: myWindow.lb_ItemActivated,
},
TextEdit{
StretchFactor: 1,
AssignTo: &myWindow.te,
ReadOnly: true,
},
},
},
HSplitter{
MaxSize:Size{600,50},
Children: []Widget{
//图像
ImageView{
Background: SolidColorBrush{Color: walk.RGB(255, 191, 0)},
//图片文件位置
Image: "img/open.png",
//和四周的边距
Margin: 5,
//定义最大拉伸尺寸
MinSize: Size{50, 50},
//显示模式
Mode: ImageViewModeZoom,
},
//按钮
PushButton{
StretchFactor:8,
Text: "摸我有惊喜",
OnClicked: func() {
ShowMsgBox("天降惊喜", "你老婆跟人跑了!")
},
},
},
},
},
}.Run()); err != nil {
log.Fatal(err)
}
}