lxn / walk

A Windows GUI toolkit for the Go Programming Language
Other
6.8k stars 885 forks source link

Tableview flicker when constantly updating contents #637

Open hankgong opened 4 years ago

hankgong commented 4 years ago

I need to write a realtime data monitoring tool with go walk. So I did a simple test with update all cells in one column every 50ms. The code is pasted below. The problem is that I can see the tableview widget kept flickering. Is there any way to fix this?

                PushButton{
                    Text: "AddPriceChecked",
                    OnClicked: func() {
                        fmt.Println("Start")
                        go func() {
                            for {
                                for i, x := range mw.model.items {
                                    // if x.checked {
                                        x.Price++
                                        mw.model.PublishRowChanged(i)
                                    // }
                                }
                                time.Sleep(50 * time.Millisecond)
                                // fmt.Println("test")
                            }
                        }()

                        // for i, x := range mw.model.items {
                        //  x.Price++
                        //  mw.model.PublishRowchanged(i)
                        // }
                    },
lxn commented 4 years ago

This should be fixed by https://github.com/lxn/walk/commit/e4edf856f3dbf0583137497f7dab032b734714df.

You should wrap any call from another goroutine into walk, like mw.model.PublishRowChanged(i) with the Synchronize method:

go func() {
    for {
        mw.Synchronize(func(){
            for i, x := range mw.model.items {
                // if x.checked {
                    x.Price++
                    mw.model.PublishRowChanged(i)
                // }
            }
        })
        time.Sleep(50 * time.Millisecond)
        // fmt.Println("test")
    }
}()
hankgong commented 4 years ago

Thanks!!! I did a test on my original code with your new release. It actually fixed the problem.

Do I still need to call mw.Synchronize with your fix? I don't see any difference when I tested with/without it.

lxn commented 4 years ago

Yes, please always use Synchronize from other goroutines, or you may get weird bugs that could be hard to track down.

lxn commented 4 years ago

With https://github.com/lxn/walk/commit/afd79bfa0f216cd28917d10cd49d2abee3ecfdb0 you can update contiguous ranges of items more efficiently:

go func() {
    for {
        mw.Synchronize(func(){
            for i, x := range mw.model.items {
                // if x.checked {
                    x.Price++
                // }
            }
            mw.model.PublishRowsChanged(0, len(mw.model.items) - 1)
        })
        time.Sleep(50 * time.Millisecond)
        // fmt.Println("test")
    }
}()
hankgong commented 4 years ago

There is one more bug. When the data kept updating, if you left-click & hold on the data item or use scrollbar to scroll data, the program will freeze. I think the table widget was doing some unnecessary repaint response.