教程三:go语言windows gui界面开发之walk 控件学习第二节之进度条

本文主要是介绍教程三:go语言windows gui界面开发之walk 控件学习第二节之进度条,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、任务栏进度条

1.1 实现思路

1.1.1 START(启动)按钮:启动进度条间隔100毫秒进度+1;
  • 第一步:新建Dialog窗口, 即创建*walk.Dialog类型变量dlg ;
  • 第二步:新建START按钮,即*walk.PushButton类型变量startBtn;
  • 第三步:dlg.ProgressIndicator().SetTotal(100)设置进度条总长;
  • 第四部:dlg.ProgressIndicator().SetCompleted(i)更新进度条当前进度,i就是更新后的值;
  • 第五步:第三步、第四部写在第二步创建的按钮点击事件中即可。
1.1.2 Paused(暂停)按钮:暂停进度条,并且进度条显示黄色;
  • 第一步:新建var stopChan chan struct{}通道,长度为1;
  • 第二步:Paused按钮事件时,向通道stopChan 写入数据stopChan <-struct{}{};
  • 第三步:此时START按钮拉起的进度条协程中向stopChan 写数据会阻塞,即实现暂停进度条;
1.1.3 Normal(恢复)按钮:恢复进度条进度,并且进度条恢复绿色
  • Normal按钮事件时,从通道stopChan中读取一次数据即可;
1.1.4 Error(出错)按钮:进度出错时使用,进度暂停,并且进度显示变红,
  • Error按钮事件时,向通道stopChan 写入数据stopChan <-struct{}{};
1.1.5 NoProgress(无进度状态)按钮:取消进度
  • 通知进度条进度接口退出,同时清除进度;
  • 实现:此处直接关闭通道stopChan ,在START任务重recover掉,比较暴力;
1.1.6 Indeterminate(不确定状态)按钮:取消进度
  • 该状态根据自己实际业务实现,此处略去;

1.2 效果图如下:

在这里插入图片描述
在这里插入图片描述

1.3代码如下

// main.go文件
package mainimport (. "log""os""runtime/debug""time""github.com/lxn/walk"
)var log *Logger
var stopChan chan struct{}func init() {log = CreateLogService()stopChan = make(chan struct{}, 1)
}// 创建日志服务
func CreateLogService() *Logger {file := "log.txt"logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm) // 以读写方式打开文件,如果没有该名称文件则自动创建,以追加的方式写入文件if err != nil {return nil}logger := New(logFile, "[logInfo:]", LstdFlags|Lshortfile) // 将文件设置为loger作为输出return logger
}func main() {defer func() {err := recover()if err != nil {log.Printf("err:%s", err)log.Printf("stack:%s.", debug.Stack())}}()if _, err := RunMyDialog(nil); err != nil {log.Fatal(err)}
}type MyDialog struct {*walk.Dialogui myDialogUI
}func (dlg *MyDialog) setState(state walk.PIState) {if err := dlg.ProgressIndicator().SetState(state); err != nil {log.Print(err)}
}func RunMyDialog(owner walk.Form) (int, error) {dlg := new(MyDialog)if err := dlg.init(owner); err != nil {return 0, err}dlg.SetLayout(walk.NewHBoxLayout())dlg.ui.indeterminateBtn.Clicked().Attach(func() {log.Println("SetState indeterminate")dlg.setState(walk.PIIndeterminate)})dlg.ui.noProgressBtn.Clicked().Attach(func() {log.Println("SetState noprogress")close(stopChan)dlg.setState(walk.PINoProgress)})dlg.ui.normalBtn.Clicked().Attach(func() {log.Println("SetState normal")<-stopChandlg.setState(walk.PINormal)})dlg.ui.errBtn.Clicked().Attach(func() {log.Println("SetState error")stopChan <- struct{}{}dlg.setState(walk.PIError)})dlg.ui.pausedBtn.Clicked().Attach(func() {log.Println("SetState paused")stopChan <- struct{}{}dlg.setState(walk.PIPaused)})dlg.ui.startBtn.Clicked().Attach(func() {go func() {defer func() {recover()log.Println("start rent abort.")dlg.ProgressIndicator().SetCompleted(0)stopChan = make(chan struct{}, 1)}()dlg.ProgressIndicator().SetTotal(100)var i uint32for i = 0; i < 100; i++ {stopChan <- struct{}{}log.Println("SetProgress", i)time.Sleep(100 * time.Millisecond)if err := dlg.ProgressIndicator().SetCompleted(i); err != nil {log.Print(err)}<-stopChan}}()})return dlg.Run(), nil
}// dialog_ui.go
// THIS FILE WAS GENERATED BY A TOOL, DO NOT EDIT!package mainimport ("github.com/lxn/walk"
)type myDialogUI struct {noProgressBtn    *walk.PushButtonindeterminateBtn *walk.PushButtonnormalBtn        *walk.PushButtonerrBtn           *walk.PushButtonpausedBtn        *walk.PushButtonstartBtn         *walk.PushButton
}func (w *MyDialog) init(owner walk.Form) (err error) {if w.Dialog, err = walk.NewDialog(owner); err != nil {return err}succeeded := falsedefer func() {if !succeeded {w.Dispose()}}()var font *walk.Fontif font == nil {font = nil}w.SetName("Dialog")if err := w.SetClientSize(walk.Size{598, 300}); err != nil {return err}if err := w.SetTitle(`Dialog`); err != nil {return err}// noProgressBtnif w.ui.noProgressBtn, err = walk.NewPushButton(w); err != nil {return err}w.ui.noProgressBtn.SetName("noProgressBtn")if err := w.ui.noProgressBtn.SetBounds(walk.Rectangle{40, 60, 161, 23}); err != nil {return err}if err := w.ui.noProgressBtn.SetText(`NoProgress`); err != nil {return err}if err := w.ui.noProgressBtn.SetMinMaxSize(walk.Size{0, 0}, walk.Size{161, 16777215}); err != nil {return err}// indeterminateBtnif w.ui.indeterminateBtn, err = walk.NewPushButton(w); err != nil {return err}w.ui.indeterminateBtn.SetName("indeterminateBtn")if err := w.ui.indeterminateBtn.SetBounds(walk.Rectangle{40, 90, 161, 23}); err != nil {return err}if err := w.ui.indeterminateBtn.SetText(`Indeterminate`); err != nil {return err}if err := w.ui.indeterminateBtn.SetMinMaxSize(walk.Size{0, 0}, walk.Size{161, 16777215}); err != nil {return err}// normalBtnif w.ui.normalBtn, err = walk.NewPushButton(w); err != nil {return err}w.ui.normalBtn.SetName("normalBtn")if err := w.ui.normalBtn.SetBounds(walk.Rectangle{40, 120, 161, 23}); err != nil {return err}if err := w.ui.normalBtn.SetText(`Normal`); err != nil {return err}if err := w.ui.normalBtn.SetMinMaxSize(walk.Size{0, 0}, walk.Size{161, 16777215}); err != nil {return err}// errBtnif w.ui.errBtn, err = walk.NewPushButton(w); err != nil {return err}w.ui.errBtn.SetName("errBtn")if err := w.ui.errBtn.SetBounds(walk.Rectangle{40, 150, 161, 23}); err != nil {return err}if err := w.ui.errBtn.SetText(`Error`); err != nil {return err}// pausedBtnif w.ui.pausedBtn, err = walk.NewPushButton(w); err != nil {return err}w.ui.pausedBtn.SetName("pausedBtn")if err := w.ui.pausedBtn.SetBounds(walk.Rectangle{40, 180, 161, 23}); err != nil {return err}if err := w.ui.pausedBtn.SetText(`Paused`); err != nil {return err}// startBtnif w.ui.startBtn, err = walk.NewPushButton(w); err != nil {return err}w.ui.startBtn.SetName("startBtn")if err := w.ui.startBtn.SetBounds(walk.Rectangle{290, 180, 75, 23}); err != nil {return err}if err := w.ui.startBtn.SetText(`START`); err != nil {return err}// Tab ordersucceeded = truereturn nil
}

二、弹窗进度条

2.1 实现思路

  • 新建*walk.ProgressBar进度控件progressBar
  • 设置进度条范围progressBar.SetRange(0, 100),只有进度条的当前值为该范围才会有进度效果;
  • 设置进度条悬窗提示当前进度,progressBar.WidgetBase.SetToolTipText(strconv.FormatInt(n, 10));
  • 更新进度条当前值progressBar.SetValue(int(n));

2.2 效果图如下

在这里插入图片描述

2.3 实现代码

package mainimport ("log""os""strconv""time""github.com/lxn/walk". "github.com/lxn/walk/declarative""github.com/lxn/win"
)var mainWindow *walk.MainWindowvar logger *log.Logger// 创建日志服务
func CreateLogService() *log.Logger {file := "log.txt"logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm) // 以读写方式打开文件,如果没有该名称文件则自动创建,以追加的方式写入文件if err != nil {return nil}logger := log.New(logFile, "[logInfo:]", log.LstdFlags|log.Lshortfile) // 将文件设置为loger作为输出return logger
}
func init() {logger = CreateLogService()
}
func main() {var hWnd win.HWND// 主界面MainWindow{AssignTo: &mainWindow,Title:    "ProgressBar Window",Icon:     "icon.png",Size:     Size{Width: 600, Height: 372},Layout:   VBox{},Children: []Widget{PushButton{MinSize: Size{Width: 60, Height: 37},MaxSize: Size{Width: 60, Height: 37},Text:    "显示进度条",OnClicked: func() {doProgress()},},},}.Create()hWnd = mainWindow.Handle()currStyle := win.GetWindowLong(hWnd, win.GWL_STYLE)win.SetWindowLong(hWnd, win.GWL_STYLE, currStyle&(^win.WS_MAXIMIZEBOX))mainWindow.Run()
}var hWnd win.HWND
var dialog *walk.Dialog
var progressBar *walk.ProgressBar
var jindu *walk.LineEdit
var confirm *walk.PushButtonfunc doProgress() {// 进度条弹窗err := Dialog{AssignTo: &dialog,Title:    "进度条 dialog",MinSize:  Size{Width: 300, Height: 200},Layout:   VBox{},Name:     "ProgressBar",Children: []Widget{Label{Text:   "当前进度:",Row:    1,Column: 1,},LineEdit{AssignTo: &jindu,ReadOnly: true,Row:      1,Column:   2,},ProgressBar{AssignTo: &progressBar},PushButton{AssignTo: &confirm,Text:     `执行完毕,退出`,Enabled:  false, //默认不可用OnClicked: func() {// 因为弹窗关闭键被取消,按键关闭dialog.Close(0)},},},}.Create(mainWindow)if err != nil {return}// 禁止关闭hWnd = dialog.Handle()hMenu := win.GetSystemMenu(hWnd, false)win.RemoveMenu(hMenu, win.SC_CLOSE, win.MF_BYCOMMAND)// 开始跑进度条dialog.Starting().Attach(func() {go progressWorker()})dialog.Run()
}func progressWorker() {length := 100// dialog.Synchronize(func() {// 	// progressBar.SetRange(0, int(length))// 	// 进度条value的起止   value到5进度条开始做走,到10停止// 	progressBar.SetRange(5, int(length))// })go func() {defer func() {err := recover()if err != nil {logger.Printf("err:%s", err)}}()// 进度条value的起止   value到0进度条开始做走,到100停止progressBar.SetRange(0, length)}()workWithCallback(length, func(n int64) {go func() {progressBar.WidgetBase.SetToolTipText(strconv.FormatInt(n, 10))progressBar.SetValue(int(n))jindu.SetText(strconv.FormatInt(n, 10))}()})// 跑完后按键可用confirm.SetEnabled(true)
}func workWithCallback(length int, callback func(int64)) {// value从1到100for i := 1; i <= length; i++ {time.Sleep(time.Second)callback(int64(i))}
}

这篇关于教程三:go语言windows gui界面开发之walk 控件学习第二节之进度条的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/700961

相关文章

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

Windows 上如果忘记了 MySQL 密码 重置密码的两种方法

《Windows上如果忘记了MySQL密码重置密码的两种方法》:本文主要介绍Windows上如果忘记了MySQL密码重置密码的两种方法,本文通过两种方法结合实例代码给大家介绍的非常详细,感... 目录方法 1:以跳过权限验证模式启动 mysql 并重置密码方法 2:使用 my.ini 文件的临时配置在 Wi

如何为Yarn配置国内源的详细教程

《如何为Yarn配置国内源的详细教程》在使用Yarn进行项目开发时,由于网络原因,直接使用官方源可能会导致下载速度慢或连接失败,配置国内源可以显著提高包的下载速度和稳定性,本文将详细介绍如何为Yarn... 目录一、查询当前使用的镜像源二、设置国内源1. 设置为淘宝镜像源2. 设置为其他国内源三、还原为官方

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

Maven的使用和配置国内源的保姆级教程

《Maven的使用和配置国内源的保姆级教程》Maven是⼀个项目管理工具,基于POM(ProjectObjectModel,项目对象模型)的概念,Maven可以通过一小段描述信息来管理项目的构建,报告... 目录1. 什么是Maven?2.创建⼀个Maven项目3.Maven 核心功能4.使用Maven H

Windows Docker端口占用错误及解决方案总结

《WindowsDocker端口占用错误及解决方案总结》在Windows环境下使用Docker容器时,端口占用错误是开发和运维中常见且棘手的问题,本文将深入剖析该问题的成因,介绍如何通过查看端口分配... 目录引言Windows docker 端口占用错误及解决方案汇总端口冲突形成原因解析诊断当前端口情况解

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注

Qt中QGroupBox控件的实现

《Qt中QGroupBox控件的实现》QGroupBox是Qt框架中一个非常有用的控件,它主要用于组织和管理一组相关的控件,本文主要介绍了Qt中QGroupBox控件的实现,具有一定的参考价值,感兴趣... 目录引言一、基本属性二、常用方法2.1 构造函数 2.2 设置标题2.3 设置复选框模式2.4 是否