andlabs / ui

Platform-native GUI library for Go.
Other
8.33k stars 651 forks source link

Progressbar not updating from go routine? #298

Closed philiplb closed 6 years ago

philiplb commented 6 years ago

Hi, my progressbar just gets stuck here with zero progress. Do you know why?

type progress func(current, total int)

func foo(p progress) {
    go func() {
        for i := 1; i <= 100; i++ {
            time.Sleep(100 * time.Millisecond)
            p(i, 100)
        }
    }()
}

myButton.OnClicked(func(button *ui.Button) {
    button.Disable()
    foo(func(current, total int) {
        value := int(float64(current) / float64(total) * 100.0)
        progressBar.SetValue(value)
    })
    button.Enable()
})

Strange: Also the button doesn't get disabled?

If this pattern doesn't work at all, how would you recommend to have a heavy function reporting progress to the UI without blocking it?

andlabs commented 6 years ago

Correct; you can't update the progressbar from another goroutine. You can call ui.QueueMain(), which will cause the function you pass in to be run on the main goroutine; it returns immediately, so you can continue your work.

philiplb commented 6 years ago

That works fine, thank you! :) For the button-issue: That was a logic error by me. In the above snipped, it gets disabled and immediatly enabled again. All in all, it must look like this:

myButton.OnClicked(func(button *ui.Button) {
    button.Disable()
    foo(func(current, total int) {
        ui.QueueMain(func() {
            value := int(float64(current) / float64(total) * 100.0)
            progressBar.SetValue(value)
            if current == total {
                button.Enable()
            }
        })
    })
})
hairichuhe commented 6 years ago

I have a problem like this,how can I write this with chan

var cnum = make(chan int, 8)
var pbc = make(chan int)
var num= 100
type progress func(current, total int)
generatebutton.OnClicked(func(*ui.Button) {
            generatebutton.Disable()
            pbar.Show()
            checkProgress(func(current, total int) {
                ui.QueueMain(func() {
                    value := int(float64(current) / float64(total) * 100.0)
                    pbar.SetValue(value)
                    if current == total {
                        generatebutton.Enable()
                        pbar.Hide()
                    }
                })
            })
            for i := 0; i < num; i++ {
                cnum <- 1
                go createqrcode()
            }
        })
func createqrcode() {
    time.Sleep(400 * time.Millisecond)
    <-cnum
    pbc <- 1
}

func checkProgress(p progress) {
    go func() {
        for i := 1; i <= num; i++ {
            <-pbc
            fmt.Println(i)
            p(i, num)
        }
    }()
}