前言:在最近的开发过程中,我需要使用 Golang 完成数据处理任务。为了避免重复工作,并且考虑到同事也有类似需求,我决定利用 Walk 框架构建一个可视化的可执行程序,以提高工作效率。
Walk: 用 Go 语言开发轻量级 Windows GUI 框架
Walk 是一款基于 Go 语言开发的轻量级 GUI 框架,专注于构建 Windows 平台的桌面应用程序。它通过封装 Windows API,提供声明式的界面构建方式,支持常见的 GUI 组件和事件处理。
学习资源
- 官方文档:https://github.com/lxn/walk
- 示例代码库:https://github.com/lxn/walk-examples
- Go 开发者社区:https://golang.org
备注 :最下方有Walk
组件及属性详情,和示例代码。
框架特点
- 仅支持 Windows:Walk 是专注于 Windows 平台的 GUI 框架,无法用于跨平台开发。
- 声明式 UI:通过类似 HTML 的结构化方式定义界面,代码清晰易读。
- 丰富的组件:支持窗口、按钮、标签、文本框、列表、表格、菜单等常用组件。
- 事件驱动:通过回调函数处理用户交互事件,逻辑直观简单。
- 轻量高效:直接基于 Windows API,性能优异,适合追求高效的本地应用开发。
适用场景
- 快速开发 Windows 工具或管理程序。
- 需要直接调用 Windows API 的高性能场景。
- 针对单一平台的桌面应用程序开发。
与跨平台 GUI 框架(如 Qt、Electron)相比,Walk 更加轻量,适合小型项目或对性能要求较高的本地化应用。
优缺点分析
优点:
- 轻量高效: 基于 Windows API,性能优异。
- 简洁直观: 声明式 UI 定义方式更贴近 Go 的开发习惯。
- 快速上手: 学习成本低,适合小型项目。
缺点:
- 仅限 Windows: 无法满足跨平台需求。
- 功能有限: 对复杂动画和现代 GUI 特效支持较弱。
- 文档较少: 社区支持和生态相对较弱。
安装与环境配置
在开始之前,请确保以下内容已准备好:
安装 Go 开发环境
如果尚未安装 Go,请访问 Go 官方下载页面 下载并安装最新版本(建议使用 Go 1.18 或更高版本)。
配置 Go 环境变量
安装完成后,确保环境变量配置正确:
-
在终端中运行
go version
,确认安装成功。 -
配置
GOPATH
和
GOROOT
,例如:
export GOPATH=$HOME/go export PATH=$PATH:$GOPATH/bin
安装 Walk 和相关依赖
使用以下命令安装 Walk 和 Windows API 相关的依赖库:
go get github.com/lxn/walk
go get github.com/lxn/win
这些库用于开发 Windows GUI 应用程序。
创建清单文件 (test.manifest
)
创建一个名为 test.manifest
的文件,内容为以下 XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
应用程序清单文件
本清单指定了:
- 使用版本为 6.0.0.0 的 Microsoft Windows 公共控件,以支持现代化 UI。
- 启用 DPI 感知,改善高分辨率显示器的显示效果。
- 启用管理员权限,以获得更高的权限访问。
-->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<!-- 程序的程序集标识 -->
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="SomeFunkyNameHere" type="win32"/>
<!-- 依赖 Microsoft Windows 公共控件 -->
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"/>
</dependentAssembly>
</dependency>
<!-- 应用程序设置 -->
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<!-- 启用 DPI 感知,改善高分辨率显示器的缩放体验 -->
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
<!-- 请求管理员权限 -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
编译清单文件为资源文件
使用 rsrc
工具将清单文件编译为 .syso
格式的资源文件:
安装 rsrc
工具
在终端中运行以下命令安装工具:
go get github.com/akavel/rsrc
编译清单文件
运行以下命令:
rsrc -manifest test.manifest -o rsrc.syso
这会生成一个 rsrc.syso
文件,供 go build
使用。
或者直接分发清单文件
可以将 test.manifest
重命名为 test.exe.manifest
,与生成的可执行文件 test.exe
一起分发。
构建应用程序
确保应用程序的 Go 源代码(如 test.go
)位于当前目录,然后运行以下命令:
go build
如果需要隐藏控制台窗口(适用于 GUI 应用程序),运行以下命令:
go build -ldflags="-H windowsgui"
运行应用程序
执行生成的 test.exe
文件即可运行应用程序。
核心组件与结构
Walk 的核心组件分为以下几类:
- 窗口(Window):包括主窗口(MainWindow)和对话框(Dialog)。
- 布局(Layout):支持水平布局(HBox)、垂直布局(VBox)和表格布局(GridView)。
- 控件(Widget):如按钮(Button)、标签(Label)、文本框(LineEdit)等。
- 事件(Event Handling):通过回调函数处理事件,例如按钮点击或文本变化。
Walk 组件详解:
1. 窗口类组件
组件 | 描述 |
---|---|
MainWindow |
应用程序主窗口。 |
Dialog |
模态对话框窗口。 |
ToolBar |
工具栏,可以包含按钮或其他控件。 |
2. 布局类组件
组件 | 描述 |
---|---|
VBox |
垂直布局,子控件按从上到下排列。 |
HBox |
水平布局,子控件按从左到右排列。 |
Grid |
网格布局,子控件按行列排列。 |
Composite |
复合组件,用于包含其他控件,同时支持自定义布局。 |
3. 输入类组件
组件 | 描述 |
---|---|
PushButton |
按钮,用于触发点击事件。 |
LineEdit |
单行文本输入框。 |
TextEdit |
多行文本输入框。 |
CheckBox |
复选框,用于布尔选择。 |
RadioButton |
单选按钮,属于单选组。 |
ComboBox |
下拉选择框,用于从列表中选择一个值。 |
SpinBox |
数值选择框,可增加或减少数值。 |
Slider |
滑块,用于调整数值。 |
4. 显示类组件
组件 | 描述 |
---|---|
Label |
文本标签,用于显示静态文本。 |
ImageView |
图像视图,用于显示图片。 |
ProgressBar |
进度条,用于显示任务进度。 |
LinkLabel |
超链接标签,支持跳转功能。 |
5. 数据展示类组件
组件 | 描述 |
---|---|
TableView |
表格视图,用于展示二维数据,支持排序和选择。 |
TreeView |
树形视图,用于显示分层数据。 |
ListBox |
列表框,用于显示一维数据。 |
6. 容器类组件
组件 | 描述 |
---|---|
ScrollView |
滚动视图,用于包含较大内容,支持滚动。 |
TabWidget |
标签页容器,用于分组内容。 |
GroupBox |
分组框,用于逻辑分组控件,通常带标题。 |
7. 其他组件
组件 | 描述 |
---|---|
Splitter |
分隔控件,用于调整子控件大小。 |
HSpacer |
水平间距控件,用于调整布局的空白距离。 |
VSpacer |
垂直间距控件,用于调整布局的空白距离。 |
Walk 组件属性详解:
属性 | 类型 | 描述 |
---|---|---|
Title |
string |
设置窗口的标题,通常显示在窗口的标题栏上。 |
Size |
Size |
设置窗口的初始大小,包含 Width 和 Height 子属性,用于分别指定宽度和高度。 |
MinSize |
Size |
设置窗口的最小尺寸,包含 Width 和 Height 子属性,确保窗口无法缩小到小于指定的尺寸。 |
Layout |
Layout |
设置窗口的布局管理器,常见的布局管理器有 VBox (垂直布局)、HBox (水平布局)、Grid (网格布局)等。 |
Children |
[]Widget |
定义窗口中的子控件,这是一个控件列表(如按钮、标签、文本框等),根据设置的布局进行排列。 |
Width |
int |
设置控件的宽度。 |
Height |
int |
设置控件的高度。 |
Text |
string |
设置控件的文本内容,常用于标签、按钮等文本显示控件。 |
OnClicked |
func() |
设置按钮等控件的点击事件处理函数。 |
Enabled |
bool |
设置控件是否可用,true 表示可用,false 表示禁用。 |
Visible |
bool |
设置控件是否可见,true 表示可见,false 表示不可见。 |
Checked |
bool |
设置复选框或单选按钮的选中状态。 |
MaxSize |
Size |
设置窗口的最大尺寸,确保窗口无法放大到大于指定的尺寸。 |
Menu |
Menu |
设置窗口的菜单栏,通常包含多个菜单项。 |
Icon |
Icon |
设置窗口的图标,通常在任务栏中显示。 |
ToolBar |
ToolBar |
设置窗口中的工具栏,通常包含按钮或其他控件。 |
Focus |
Widget |
设置窗口或控件的默认焦点控件,即当窗口打开时,首先获取焦点的控件。 |
Style |
Style |
设置控件的样式,例如按钮的外观或文本框的样式。 |
TabOrder |
int |
设置控件在 Tab 键切换时的顺序。 |
备注 :Size
是一个包含 Width
和 Height
的结构体,Layout
是一个布局管理器,Children
是包含窗口控件的列表。
示例代码
1. 简单窗口示例
以下是一个带有按钮的基本窗口示例:
package main
import (
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
)
func main() {
var mainWindow *walk.MainWindow
MainWindow{
AssignTo: &mainWindow,
Title: "Hello Walk",
Size: Size{Width: 400, Height: 300},
Layout: VBox{},
Children: []Widget{
Label{Text: "Welcome to Walk GUI!"},
PushButton{
Text: "Click Me",
OnClicked: func() {
walk.MsgBox(mainWindow, "Message", "Button Clicked!", walk.MsgBoxIconInformation)
},
},
},
}.Run()
}
运行效果:
- 窗口标题为 "Hello Walk",包含一个标签和一个按钮。
- 点击按钮会弹出一条消息框显示 "Button Clicked!"。
2. 表单与输入框示例
创建一个简单的表单,用户填写姓名后点击按钮显示欢迎消息:
package main
import (
"fmt"
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
)
func main() {
var mainWindow *walk.MainWindow
var nameEdit *walk.LineEdit
MainWindow{
AssignTo: &mainWindow,
Title: "Form Example",
Size: Size{Width: 400, Height: 200},
Layout: VBox{},
Children: []Widget{
Label{Text: "Enter your name:"},
LineEdit{AssignTo: &nameEdit},
PushButton{
Text: "Submit",
OnClicked: func() {
name := nameEdit.Text()
walk.MsgBox(mainWindow, "Welcome", fmt.Sprintf("Hello, %s!", name), walk.MsgBoxIconInformation)
},
},
},
}.Run()
}
运行效果:
- 窗口包含一个输入框和一个按钮。
- 用户输入姓名后,点击按钮会弹出欢迎消息。
3. 表格与数据绑定示例
以下示例展示如何创建一个表格控件并绑定数据:
package main
import (
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
)
type Person struct {
Name string
Age int
Email string
}
func main() {
var mainWindow *walk.MainWindow
people := []Person{
{Name: "Alice", Age: 30, Email: "alice@example.com"},
{Name: "Bob", Age: 25, Email: "bob@example.com"},
{Name: "Charlie", Age: 35, Email: "charlie@example.com"},
}
MainWindow{
AssignTo: &mainWindow,
Title: "Table Example",
Size: Size{Width: 600, Height: 400},
Layout: VBox{},
Children: []Widget{
TableView{
Columns: []TableViewColumn{
{Title: "Name", Width: 150},
{Title: "Age", Width: 50},
{Title: "Email", Width: 200},
},
Model: walk.NewReflectTableModel(people),
},
},
}.Run()
}
运行效果:
- 表格显示包含 Name、Age 和 Email 的数据。
- 数据从
people
切片中加载,支持动态更新。