Skip to content
This repository has been archived by the owner on Nov 5, 2022. It is now read-only.

panic when change label text in linelayout by goroutine #110

Closed
zhangpy opened this issue Apr 23, 2015 · 1 comment
Closed

panic when change label text in linelayout by goroutine #110

zhangpy opened this issue Apr 23, 2015 · 1 comment

Comments

@zhangpy
Copy link

zhangpy commented Apr 23, 2015

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)
}
@ben-clayton
Copy link
Contributor

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))])
            })
        }
    }()

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants