panic when change label text in linelayout by goroutine
zhangpy opened this issue · comments
panic: Cannot call Relayout() while in LayoutChildren
goroutine 7 [running]:
github.com/google/gxui/mixins/parts.(*Layoutable).Relayout(0xc2081d9790)
src/github.com/google/gxui/mixins/parts/layoutable.go:67 +0x72
github.com/google/gxui/mixins/parts.(*Layoutable).Relayout(0xc20824a3a0)
src/github.com/google/gxui/mixins/parts/layoutable.go:72 +0xcc
github.com/google/gxui/mixins.(*Label).SetText(0xc20824a240, 0x7fe070, 0x1)
src/github.com/google/gxui/mixins/label.go:52 +0xd8
main.func·002()
src/zz/words2/test/main.go:45 +0xd5
created by main.appMain
src/zz/words2/test/main.go:47 +0x69a
package main
import (
"math/rand"
"time"
"zz/words2/gxfont"
"github.com/google/gxui"
"github.com/google/gxui/drivers/gl"
"github.com/google/gxui/themes/dark"
)
func appMain(driver gxui.Driver) {
theme := dark.CreateTheme(driver)
font, err := driver.CreateFont(gxfont.Default, 500)
if err != nil {
panic(err)
}
window := theme.CreateWindow(1024, 800, "Hi")
window.SetBackgroundBrush(gxui.CreateBrush(gxui.Gray50))
cs := []string{"a", "1", "b", "2", "c", "3", "d", "4"}
layout := theme.CreateLinearLayout()
layout.SetSizeMode(gxui.Fill)
layout.SetDirection(gxui.RightToLeft)
label1 := theme.CreateLabel()
label1.SetFont(font)
changeFont1Chan := make(chan int)
go func() {
for {
<-changeFont1Chan
label1.SetText(cs[rand.Intn(len(cs))])
}
}()
label2 := theme.CreateLabel()
label2.SetFont(font)
changeFont2Chan := make(chan int)
go func() {
for {
<-changeFont2Chan
label2.SetText(cs[rand.Intn(len(cs))])
}
}()
changeFontChan := make(chan int)
go func() {
for {
<-changeFontChan
changeFont1Chan <- 1
changeFont2Chan <- 1
}
}()
layout.AddChild(label1)
layout.AddChild(label2)
window.AddChild(layout)
window.OnClose(driver.Terminate)
window.OnKeyDown(func(e gxui.KeyboardEvent) {
switch e.Key {
case gxui.KeyLeft:
changeFontChan <- 1
case gxui.KeyRight:
changeFontChan <- 1
}
})
//simulate user's action like press keyboard to trigger this change.
//it is more easy to trigger the panic with shorter sleep time.
go func() {
for {
changeFontChan <- 1
time.Sleep(time.Second)
}
}()
}
func main() {
gl.StartDriver(appMain)
}
Your problem here is with the goroutines calling SetText. GXUI does not support calls directly from goroutines other than the goroutine that executes the gl.StartDriver callback. You can however use the Driver.Call method to execute your UI code on the correct goroutine:
go func() {
for {
<-changeFont1Chan
driver.Call(func() {
label1.SetText(cs[rand.Intn(len(cs))])
})
}
}()