dontpanic92 / wxGo

Golang wxWidgets Wrapper
Other
403 stars 51 forks source link

can't force window to Repaint from within thread #10

Closed andrewarrow closed 8 years ago

andrewarrow commented 8 years ago

Here's some sample code that puts a Gauge on the screen and make the progress bar increase 1 value every second. On MacOS I don't see the progress bar update unless I drag the window around or resize it manually with the mouse. Any idea how to force the whole thing to repaint? I'm calling f.Refresh() and f.Update()

package main

import "github.com/dontpanic92/wxGo/wx"
import "time"

var g wx.Gauge

type MyFrame struct {
    wx.Frame
}

func (f *MyFrame) startUpload() {
    for {
        time.Sleep(time.Second)
        g.SetValue(g.GetValue() + 1)
        f.Refresh()
        f.Update()
    }
}

func NewMyFrame() MyFrame {
    f := MyFrame{}
    f.Frame = wx.NewFrame(wx.NullWindow, -1, "Test Thread")
    mainSizer := wx.NewBoxSizer(wx.HORIZONTAL)
    g = wx.NewGauge(f, wx.ID_ANY, 100, wx.DefaultPosition, wx.NewSize(600, 40), 0)
    f.SetSizer(mainSizer)
    mainSizer.Add(g, 100, wx.ALL|wx.EXPAND, 50)
    f.Layout()
    go f.startUpload()
    return f
}

func main() {
    wx1 := wx.NewApp()
    f := NewMyFrame()
    f.Show()
    wx1.MainLoop()
    return
}
dontpanic92 commented 8 years ago

Hi, I have tested on Linux and it works well without Refresh and Update, but I think it is implementation-dependent: calling GUI functions in secondary threads is not recommanded (http://docs.wxwidgets.org/trunk/overview_thread.html). Briefly, try sending events to the GUI thread. However I am not sure whether it is caused by wxGo's bug. I will have a test on OS X using C++.

By the way, calling Update will cause an XWindowSystem error in Linux.

andrewarrow commented 8 years ago

oh! I see, there's a better way to tell it to update on the main thread. thank u, i'll try that!

andrewarrow commented 8 years ago

well I tried a bunch of stuff, the cloest I got that compiles fine and I thought would work was:

    b := wx.NewPaintEvent()
    f.GetEventHandler().QueueEvent(b)

but still same problem. Gauge is not repainted until I manually resize window with mouse. Maybe I need to use wxThreadHelper? But I couldn't get that to compile. Could I trouble you for a new file in examples/src/ called something like gauge_with_thread/main.go?

dontpanic92 commented 8 years ago

SetValue itself is a "GUI function", which means we should call it in the GUI thread, and the window will be automatically updated without any additional operation. I have created an example named threadevent, it uses wxThreadEvent to communicate between goroutines.

andrewarrow commented 8 years ago

works great! Thanks again. closing.