Skip to content

Instantly share code, notes, and snippets.

@Michael-F-Ellis
Last active May 5, 2020 01:03
Show Gist options
  • Save Michael-F-Ellis/4df32251b0d4210c581ab34844a1eb6d to your computer and use it in GitHub Desktop.
Save Michael-F-Ellis/4df32251b0d4210c581ab34844a1eb6d to your computer and use it in GitHub Desktop.
Minimal app to reproduce a mem leak when loading image files to Fyne. See https://github.com/fyne-io/fyne/issues/348
package main
import (
"flag"
"log"
"time"
"net/http"
_ "net/http/pprof"
"fyne.io/fyne"
"fyne.io/fyne/app"
"fyne.io/fyne/canvas"
"fyne.io/fyne/layout"
"fyne.io/fyne/widget"
)
// main initializes a fyne app containing a single image which it reloads at 5s intervals
func main() {
// serve pprof
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
// define and parse command line flags
flag.Parse()
args := flag.Args()
if len(args) != 1 {
log.Fatal("One filepath is the only allowed argument")
}
graphWidgets.graphFilePath = args[0]
// initialize the app with our custom theme.
a := app.New()
// the top-level (and so far the only) window
w := a.NewWindow("MemLeak")
w.SetContent(widget.NewVBox(
graphPanel(),
))
// Launch update tasks
go graphUpdater()
// Display and run the app
w.ShowAndRun()
}
var graphWidgets struct {
graphBox *widget.Box
container *fyne.Container
graph *canvas.Image
graphFilePath string
}
// graphPanel creates the graph Panel that fills the entire window below the
// header and menu bar
func graphPanel() *widget.Box {
var err error
graphWidgets.graph, err = getGraph(graphWidgets.graphFilePath)
if err != nil {
log.Fatal("can't load graph")
}
// force fit to bottom 2/3 of Pi touchscreen
graphWidgets.container = fyne.NewContainerWithLayout(layout.NewFixedGridLayout(fyne.NewSize(800, 320)), graphWidgets.graph)
graphWidgets.graphBox = widget.NewHBox(graphWidgets.container)
return graphWidgets.graphBox
}
// graphUpdater reloads the graph every 5 seconds
func graphUpdater() {
for {
time.Sleep(5 * time.Second)
newgraph, err := getGraph(graphWidgets.graphFilePath)
if err != nil {
log.Fatal("getGraph failed")
}
graphWidgets.container.Objects[0] = newgraph
graphWidgets.container.Refresh()
graphWidgets.graphBox.Refresh()
}
}
// getGraph returns a canvas image of a graph
func getGraph(fpath string) (img *canvas.Image, err error) {
img = canvas.NewImageFromFile(fpath)
img.SetMinSize(fyne.NewSize(800, 320)) // force fit to width and 1/4 height of Pi touchscreen
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment