教程三: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

相关文章

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Ubuntu固定虚拟机ip地址的方法教程

《Ubuntu固定虚拟机ip地址的方法教程》本文详细介绍了如何在Ubuntu虚拟机中固定IP地址,包括检查和编辑`/etc/apt/sources.list`文件、更新网络配置文件以及使用Networ... 1、由于虚拟机网络是桥接,所以ip地址会不停地变化,接下来我们就讲述ip如何固定 2、如果apt安

Go路由注册方法详解

《Go路由注册方法详解》Go语言中,http.NewServeMux()和http.HandleFunc()是两种不同的路由注册方式,前者创建独立的ServeMux实例,适合模块化和分层路由,灵活性高... 目录Go路由注册方法1. 路由注册的方式2. 路由器的独立性3. 灵活性4. 启动服务器的方式5.

PyCharm 接入 DeepSeek最新完整教程

《PyCharm接入DeepSeek最新完整教程》文章介绍了DeepSeek-V3模型的性能提升以及如何在PyCharm中接入和使用DeepSeek进行代码开发,本文通过图文并茂的形式给大家介绍的... 目录DeepSeek-V3效果演示创建API Key在PyCharm中下载Continue插件配置Con

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

Spring Boot整合log4j2日志配置的详细教程

《SpringBoot整合log4j2日志配置的详细教程》:本文主要介绍SpringBoot项目中整合Log4j2日志框架的步骤和配置,包括常用日志框架的比较、配置参数介绍、Log4j2配置详解... 目录前言一、常用日志框架二、配置参数介绍1. 日志级别2. 输出形式3. 日志格式3.1 PatternL