I am following this tutorial for using GIO, a cross platform GUI library. I am at a point where I feel the code should be more organized so I came up with a neat solution for separating the various stages of creating a window and it's contents. Basically, I just refactored the concepts from the tutorial into something I am more comfortable with.
So I have 3 files:
main.go:
package main
import (
"log"
"os"
"toucam/windows"
"gioui.org/app"
"gioui.org/op"
"gioui.org/widget/material"
)
var ops op.Ops
func main() {
go func() {
// create new window
w := app.NewWindow(
app.Title("Egg Timer"),
//app.Maximized.Option(),
)
if err := run(w); err != nil {
log.Fatal(err)
}
os.Exit(0)
}()
app.Main()
}
func run(w *app.Window) error {
theme := material.NewTheme()
mw := windows.NewMainWindow(theme)
for {
switch e := w.NextEvent().(type) {
case app.FrameEvent:
mw.Layout(app.NewContext(&ops, e))
case app.DestroyEvent:
return e.Err
}
}
}
windows/window.go:
package windows
import (
"gioui.org/layout"
"gioui.org/widget/material"
)
type window struct {
title string
theme *material.Theme
Layout func(gtx layout.Context) layout.Dimensions
}
and windows/main.go:
package windows
import (
"gioui.org/layout"
"gioui.org/widget"
"gioui.org/widget/material"
)
var startButton widget.Clickable
func NewMainWindow(theme *material.Theme) window {
mainWindow := window{
title: "TOUCAM",
theme: theme,
Layout: func(gtx layout.Context) layout.Dimensions {
//Window layout goes here
return layout.Flex{
Axis: layout.Vertical,
Spacing: layout.SpaceStart,
}.Layout(gtx,
layout.Rigid(
func(gtx layout.Context) layout.Dimensions {
btn := material.Button(theme, &startButton, "Start")
return btn.Layout(gtx)
},
),
)
},
}
return mainWindow
}
As you can see, what I've tried to do is isolate the structure of a given window into it's own file. The result is an empty window. There is no button. I'm quite unsure as to why.
Here is a repo with the exact code you can use to test.
Can anyone identify what I've done wrong?
You are missing the call to e.Frame(&ops)
. Here is the fixed app.FrameEvent
event handler in main.go:
case app.FrameEvent:
mw.Layout(app.NewContext(&ops, e))
e.Frame(&ops)
As stated in the documentation
Frame completes the FrameEvent by drawing the graphical operations from ops into the window.
Therefore the button is not drawn in your case, because the graphical operations for drawing it were created only, but not yet executed (i.e. the operations were never applied to the frame).