visualfc / atk

Another Golang Tcl/Tk binding GUI ToolKit
GNU Lesser General Public License v2.1
97 stars 19 forks source link

tk.Async 函数刷新GUI控件问题反馈 #21

Closed 52LY closed 3 years ago

52LY commented 3 years ago

代码如下:

func tobpg(label tk.Widget, infotext *tk.TextEx, cmdargs []string, inputimgs []string) {
    start := time.Now()

    for i, in := range inputimgs {
        cmdargs1 := append(cmdargs, []string{"-o", in + ".bpg", in}...)

        cmd := exec.Command("bpgenc", cmdargs1...)
        cmd.Start()

        cmd.Wait() // 阻塞至cmd命令完成

        fmt.Println(inputimgs[i],": finished") // cmd打印第【i】个完成信息

        // GUI显示第【i】个完成信息
        tk.Async(func() { 
            infotext.AppendText(inputimgs[i] + ": finished\n") 
            infotext.SetSeeEnd()
        })

    }

    end := time.Now()
    delta := end.Sub(start)

    v := fmt.Sprintf("转码进度: 完成%v个图片转码,耗时:%s", len(inputimgs), delta)

    tk.Async(func() { label.SetNativeAttribute("text",v) })
}

for循环执行cmd命令,每完成一个cmd命令,就在Text控件刷新第几个cmd命令完成信息

StartBtn.OnCommand(func() { 
     go tobpg(......) 
})

点击这个StartBtn按钮之后,结果如下图:

Text控件刷新和cmd窗口刷新 应该是一模一样的

visualfc commented 3 years ago

tk.Async 中使用的 func() ,需要注意在 for 循环中闭包中外部变量的使用。注意下面例子中 i 和 n 的区别。

package main

func main() {
    var fns [3]func()
    for i := 0; i < 3; i++ {
        n := i
        fn := func() {
            println(i, n)
        }
        fns[i] = fn
    }
    fns[0]()
}
52LY commented 3 years ago

😄 感谢感谢,在使用 tk.Async 之前,tmp := in ,再把 tmp 传给 tk.Async 就行了