本文主要是介绍教程三: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 控件学习第二节之进度条的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!