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

相关文章

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

GO语言短变量声明的实现示例

《GO语言短变量声明的实现示例》在Go语言中,短变量声明是一种简洁的变量声明方式,使用:=运算符,可以自动推断变量类型,下面就来具体介绍一下如何使用,感兴趣的可以了解一下... 目录基本语法功能特点与var的区别适用场景注意事项基本语法variableName := value功能特点1、自动类型推

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

Java Scanner类解析与实战教程

《JavaScanner类解析与实战教程》JavaScanner类(java.util包)是文本输入解析工具,支持基本类型和字符串读取,基于Readable接口与正则分隔符实现,适用于控制台、文件输... 目录一、核心设计与工作原理1.底层依赖2.解析机制A.核心逻辑基于分隔符(delimiter)和模式匹

Go之errors.New和fmt.Errorf 的区别小结

《Go之errors.New和fmt.Errorf的区别小结》本文主要介绍了Go之errors.New和fmt.Errorf的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考... 目录error的基本用法1. 获取错误信息2. 在条件判断中使用基本区别1.函数签名2.使用场景详细对

基于Java开发一个极简版敏感词检测工具

《基于Java开发一个极简版敏感词检测工具》这篇文章主要为大家详细介绍了如何基于Java开发一个极简版敏感词检测工具,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录你是否还在为敏感词检测头疼一、极简版Java敏感词检测工具的3大核心优势1.1 优势1:DFA算法驱动,效率提升10

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程