visualfc/atk

用go程去刷下控件内容没有作用

52LY opened this issue · 2 comments

52LY commented

代码如下:

package main

import "github.com/visualfc/atk/tk"
import "strings"
import "strconv"
import "time"
import "fmt"

type Window struct { *tk.Window }


func f1(x float64) float64 {
   return x * x - x
}

func integrate_f1(a, b  float64, N int) float64 {
   // 0 23 10000000001
   var s float64 = 0
   dx := (b - a) / float64(N)

   for i:=0; i<N; i++ {
       s += f1(a + float64(i) * dx)
   }
   
   return s * dx
}

func cal(input string, resch chan string) {
    start := time.Now()

    inputnum := strings.Split(input," ")
    a,_ := strconv.ParseFloat(inputnum[0], 64)
    b,_ := strconv.ParseFloat(inputnum[1], 64)
    N,_ := strconv.Atoi(inputnum[2])
    res := integrate_f1(a, b, N)

    end := time.Now()
    
    delta := end.Sub(start)
    
    resch <- fmt.Sprintf("计算结果: \nres is %v \ntime: %s", res, delta)
    
}

func NewWindow() *Window {
    
    s1 := make(chan string)
    
    mw := &Window{}
    mw.Window = tk.RootWindow()
    
    labelf := tk.NewLabel(mw, "计算阻塞")
    entryf := tk.NewEntry(mw,)
    labels := tk.NewLabel(mw, "计算结果: ")
    btn1 := tk.NewButton(mw,"开始计算",tk.WidgetAttrInitUseTheme(true))
    btn2 := tk.NewButton(mw,"退出",tk.WidgetAttrInitUseTheme(true))

    btn1.SetTakeFocus(false)
    btn2.SetTakeFocus(false)

    // go运行耗时函数,然后go刷新label控件内容,但是内容没有刷新
    // labels.SetText(<-s1)这样的话可以刷新,但是界面会阻塞
    // go func() { fmt.Println(<-s1) }() 这样打印结果也没问题,界面不会阻塞
    btn1.OnCommand(func() { 
        go cal(entryf.Text(),s1)
        go func() { labels.SetText(<-s1) }()
    })
    
    btn2.OnCommand(func() { tk.Quit() })

    vbox := tk.NewVPackLayout(mw)
    vbox.SetPaddingN(5, 5)
    vbox.AddWidgetEx(labelf, 0, false, 6)
    vbox.AddWidgetEx(entryf, 0, false, 6)
    vbox.AddWidgetEx(labels, 0, false, 6)
    vbox.AddWidgetEx(btn1, 0, false, 6)
    vbox.AddWidgetEx(btn2, 0, false, 6)

    return mw
}

func main() {
    win := func() {
        mw := NewWindow()
        mw.SetTitle("阻塞窗口例子")
        mw.ResizeN(600, 600)
        mw.Center(nil)
        mw.ShowNormal()
    }
    
    tk.MainLoop(win)
}

一个原则是永远不要在 go func() 中 直接对 UI 进行读和写,需要时可以使用 tk.Async 函数

btn1.OnCommand(func() {
	in := entryf.Text() 
       // 先从 ui 中获取值,再运行 go func
	go cal(in, s1)
	go func() {
		out := <-s1
                // 先获取值,再通过 Async 对 ui 读写
		tk.Async(func() {
			labels.SetText(out) 
		})
	}()
})
52LY commented

感谢