Go Fyne Scrolling behaviour with drawn objects in containers not providing scrolls or error

124 Views Asked by At

I am struggling to get scrolling behaviour working. The code has two rectangles and a diagonal line just to give some larger container continence to wrap inside a scroll container which should produce the desired scrolling behaviour when user resize the window ? Go1.21.3 , fyne cli version: v2.3.5, win11. I am not getting any scroll bars. I have tried many variations for hours.

I wish to produce a very long bar chart ( multiple lines and rectangles) which the user will need to scroll along. Scrolling is a standard use case applicable to many GUI’s. https://developer.fyne.io/api/v2.4/container/scroll.html is a bit dry on examples.

package main

import (
    "image/color"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/canvas"
    "fyne.io/fyne/v2/container"
)

func main() {
    myApp := app.New()
    w := myApp.NewWindow("Rectangle")

    rect := canvas.NewRectangle(color.White) // just a white rectangle
    rect.StrokeColor = color.Opaque
    rect.Resize(fyne.NewSize(150, 150))

    rect2 := canvas.NewRectangle(color.Gray{}) // just a gray rectangle
    rect2.Resize(fyne.NewSize(150, 150))
    rect2.Move(fyne.NewPos(150, 150))

    line := canvas.NewLine(color.RGBA{255, 0, 0, 255}) // just a red line diagonal
    line.StrokeWidth = 5
    line.Position1 = fyne.NewPos(0, 0)
    line.Position2 = fyne.NewPos(300, 300)

    // Create a fixed-size container for the content
    content := container.NewWithoutLayout(rect2, line, rect) //place objects into content
    content.Resize(fyne.NewSize(300, 300))                   // Set a fixed size

    // Create a scrollable container placing the content into it (content is bigger than container)
    scrollContainer := container.NewVScroll(content) // NewScroll , NewVScroll , try different /

    w.SetContent(scrollContainer)

    w.ShowAndRun()
}

2

There are 2 best solutions below

3
On

The scroll container uses the content MinSize to figure out what space is going to have to scroll I think. And your container without layout doesn’t have a minimum size configured (the layout would normally take care of that for you).

1
On

Ok I have found a work around but your not going to like it, as it feels more like a hack than an design intent by fyne. All I did is add a canvas.text element.

container.Scroll requires a canvas object. func NewScroll(content fyne.CanvasObject) *Scroll.

canvas.Rectangle is a canvas object ( but only one expands to the extents // not scrollable) Two or more canvas.Rectangle arainged in a container should negate this functionality and so we should have a scrollable behaviour. But no ? Is it min size problem as kindly sugested by andy.xyz I tried setting min size on rectangles but no effect ( un-comment in code to test ). This can also be seen in fyne-master/ container.go I.e SetMinSize(fyne.NewSize(800, 800))

I then added a canvas.text to the container and the scroll bars appeared. But you have to have a long blank line of text the length of your graphic and it scrolls horizontally. You will get :- SetMinSize has no effect as the smallest size this canvas object can be is based on its font size and content. I.e we are manually setting a long string to activate the Hscroll. See code new scroll is only producing h scroll. To get v scroll perhaps you need a whole lot of /n new lines in the back ground. ?

Conclusion / advice. I have spent 2 days on this little thing. I now have a horizontally scrolling canvas of multiple canvas objects in preparation boiler plate for making by desired graphics. However I don't advise this method.” hacky” Hopefully Fyne developers may make this aspect more user friendly / detailed + short snippet examples. If I may give a hint I think scroll is expecting a canvas object or slice of canvas objects not a container of canvas objects. Also note I am using without layout manually arraigning elements. It would be nice if this canvas could work with SVG.

    package main
import (
    "image/color"
    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/canvas"
    "fyne.io/fyne/v2/container"
)

func main() {
    myApp := app.New()
    w := myApp.NewWindow("Rectangle")

    rect := canvas.NewRectangle(color.White) // just a white rectangle
    rect.StrokeColor = color.Opaque
    rect.Resize(fyne.NewSize(150, 150))
    //rect.SetMinSize(fyne.NewSize(150, 150)) //try

    rect2 := canvas.NewRectangle(color.Gray{}) // just a gray rectangle
    rect2.Resize(fyne.NewSize(150, 150))
    rect2.Move(fyne.NewPos(150, 150))
    //rect2.SetMinSize(fyne.NewSize(150, 150)) // try

    line := canvas.NewLine(color.RGBA{255, 0, 0, 255}) // just a red line diagonal
    line.StrokeWidth = 5
    line.Position1 = fyne.NewPos(0, 0)
    line.Position2 = fyne.NewPos(300, 300)  
// addint this text span kicks the Hscroll to start working
    stext := canvas.NewText("scroll space keeper--->   
      >-text v long length hiden spans the length of scroll ", color.Black) // just text
      // set all text on one line ( wraped only for code readablity)
    
    // Create a fixed-size container for the content
    content := container.NewWithoutLayout(stext,rect2, line, rect) //place objects into content
    
    content.Resize(fyne.NewSize(300, 300))                   // Set a fixed size

    scrollContainer := container.NewScroll(content) // NewScroll , NewVScroll , try different /

    w.SetContent(scrollContainer)
    w.Resize(fyne.NewSize(200, 325))

    w.ShowAndRun()
}