質問: ### 前提・実現したいこと 情報を読み込んでいることを表示する画面を作成したいです。 使用言語はgolangでGUIを表示するライブラリはwalkを使用しています。 GoでGUIを表示する ### 試したこと まず初めに、ロード画面のGUIを表示する ``` showWindow() ``` という関数を作成しました。 これはプログレスバーを表示するだけの簡単なものになっています。 次に、コンピュータの情報を取得する ``` getInfo() ``` という関数を作成しました。 これら2つはそれぞれ期待通りに動作するのを確認できています。 最後に、情報を読み込んでいる間はロード画面を表示する、ということがしたかったので Goで並列処理 を参考に以下のコードを作成しました。 ``` import ( "log" "time" "github.com/lxn/walk" . "github.com/lxn/walk/declarative" ) func main() { isFin1 := make(chan bool) isFin2 := make(chan bool) fmt.Println("Start!") go func() { // ロード画面を表示する showWindow() isFin1 <- true }() go func() { // PCの情報を取得する getInfo() isFin2 <- true }() // 情報を取得するのを待つ <-isFin1 <-isFin2 fmt.Println("PC情報の取得に成功しました。") } // 受け渡し用構造体 type MyLoadWindow struct { *walk.MainWindow progressBar *walk.ProgressBar } func showWindow() { mw := &MyLoadWindow{} // 画面サイズ取得 sizeX := 300 sizeY := 100 // 画面情報設定 MW := MainWindow{ AssignTo: &mw.MainWindow, Title: "待機中", Size: Size{ sizeX, sizeY}, Font: Font{PointSize: 12}, Layout: VBox{}, Children: []Widget{ ProgressBar{ AssignTo: &mw.progressBar, MarqueeMode: true, }, }, } if _, err := MW.Run(); err != nil { return } } func getInfo() { fmt.Println("get Info") } ``` ### 発生している問題・エラーメッセージ 上記のコードを実行すると PC情報の取得関数は動作しているが、ロード画面が表示されない ように見えるという問題が発生しました。 デバッガで実行するとshowWindow()のところも通っているように見えるのですが 単体で実行したときに表示されたプログレスバーは表示されませんでした。 並列処理というものを初めてしたのできっとそこに問題があると思うのですが どなたか何が悪いかわかる方がいたら教えていただけないでしょうか。 ※追記 よく考えてみれば<-isFin2になったらshowWindow()を終了するのような処理にするべきなのかなと思いましたが そこをどのように実現すればいいのかが思いつかなかったです... ### 補足情報(FW/ツールのバージョンなど) Windows Golang
回答: ここに同様の悩みと解決例があります。 GUIではメインスレッド(メインゴルーチン)でないとイベントループが回らないという問題は常について回ります。 walkはSynchronizeメソッドに関数を渡すとその処理がメインゴルーチンで動く仕掛けを持っています。 上記の解決例を参考に作り直してみましょう。 解決例(追記): ``` package main import ( "fmt" "log" "time" "github.com/lxn/walk" . "github.com/lxn/walk/declarative" ) func main() { fmt.Println("Start!") go func() { // PCの情報を取得する getInfo() fmt.Println("PC情報の取得に成功しました。") }() showWindow() // ウインドウが閉じるまでブロックします(閉じるまでreturnしない) } // 受け渡し用構造体 type MyLoadWindow struct { *walk.MainWindow progressBar *walk.ProgressBar } var mw = &MyLoadWindow{} func showWindow() { // 画面サイズ取得 sizeX := 300 sizeY := 100 // 画面情報設定 MW := MainWindow{ AssignTo: &mw.MainWindow, Title: "待機中", Size: Size{ sizeX, sizeY}, Font: Font{PointSize: 12}, Layout: VBox{}, Children: []Widget{ ProgressBar{ AssignTo: &mw.progressBar, MarqueeMode: true, }, }, } if _, err := MW.Run(); err != nil { log.Fatal(err) // エラーはあれば表示しましょう } } func getInfo() { time.Sleep(10 * time.Second) fmt.Println("get Info") mw.MainWindow.Synchronize(func(){mw.MainWindow.Close()}) // メインgoroutineからウインドウのクローズを呼ぶ } ```