Heim  >  Artikel  >  Backend-Entwicklung  >  Passen Sie das adaptive Rasterlayout von Fyne an

Passen Sie das adaptive Rasterlayout von Fyne an

PHPz
PHPznach vorne
2024-02-12 15:30:07872Durchsuche

自定义 Fyne 自适应网格布局

Frageninhalt

Ich ändere den Container.newadaptivegrid() der Fyne-Bibliothek, um die Breite des gerenderten Widgets basierend auf dem Verhältnis, das wir ihm übergeben, aufzuteilen. Ab sofort rendert container.newadaptivegrid() Widgets gleicher Breite in einer Reihe. Grundsätzlich (jetzt Gesamtzeilengröße/Widgets).

Mein Code:

package main

import (
    "fmt"
    "math"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/container"
    "fyne.io/fyne/v2/theme"
    "fyne.io/fyne/v2/widget"
)

func New(layout fyne.Layout, objects ...fyne.CanvasObject) *fyne.Container {
    return fyne.NewContainerWithLayout(layout, objects...)
}

func NewAdaptiveGridWithRatios(ratios []float32, objects ...fyne.CanvasObject) *fyne.Container {
    return New(NewAdaptiveGridLayoutWithRatios(ratios), objects...)
}

// Declare conformity with Layout interface
var _ fyne.Layout = (*adaptiveGridLayoutWithRatios)(nil)

type adaptiveGridLayoutWithRatios struct {
    ratios          []float32
    adapt, vertical bool
}

func NewAdaptiveGridLayoutWithRatios(ratios []float32) fyne.Layout {
    return &adaptiveGridLayoutWithRatios{ratios: ratios, adapt: true}
}

func (g *adaptiveGridLayoutWithRatios) horizontal() bool {
    if g.adapt {
        return fyne.IsHorizontal(fyne.CurrentDevice().Orientation())
    }

    return !g.vertical
}

func (g *adaptiveGridLayoutWithRatios) countRows(objects []fyne.CanvasObject) int {
    count := 0
    for _, child := range objects {
        if child.Visible() {
            count++
        }
    }

    return int(math.Ceil(float64(count) / float64(len(g.ratios))))
}

// Get the leading (top or left) edge of a grid cell.
// size is the ideal cell size and the offset is which col or row its on.
func getLeading(size float64, offset int) float32 {
    ret := (size + float64(theme.Padding())) * float64(offset)

    return float32(ret)
}

// Get the trailing (bottom or right) edge of a grid cell.
// size is the ideal cell size and the offset is which col or row its on.
func getTrailing(size float64, offset int) float32 {
    return getLeading(size, offset+1) - theme.Padding()
}

// Layout is called to pack all child objects into a specified size.
// For a GridLayout this will pack objects into a table format with the number
// of columns specified in our constructor.
func (g *adaptiveGridLayoutWithRatios) Layout(objects []fyne.CanvasObject, size fyne.Size) {
    rows := g.countRows(objects)
    cols := len(g.ratios)
    if g.horizontal() {
        cols = rows
        rows = len(g.ratios)
    }

    padWidth := float32(cols-1) * theme.Padding()
    padHeight := float32(rows-1) * theme.Padding()
    var totalRatio float32
    for _, r := range g.ratios {
        totalRatio += r
    }

    cellWidth := (float64(size.Width) - float64(padWidth)) / float64(len(g.ratios))
    cellHeight := float64(size.Height-padHeight) / float64(rows)

    if !g.horizontal() {
        cellWidth, cellHeight = cellHeight, cellWidth
        cellWidth = float64(size.Width-padWidth) / float64(rows)
        cellHeight = float64(size.Height-padHeight) / float64(len(g.ratios))
    }

    row, col := 0, 0
    i := 0
    for _, child := range objects {
        if !child.Visible() {
            continue
        }

        //ratio := g.ratios[j%len(g.ratios)]
        cellSize := fyne.NewSize(float32(cellWidth)*g.ratios[i], float32(cellHeight))

        x1 := getLeading(float64(cellSize.Width), col)
        y1 := getLeading(float64(cellSize.Height), row)
        x2 := getTrailing(float64(cellSize.Width), col)
        y2 := getTrailing(float64(cellSize.Height), row)
        fmt.Println("1s :", x1, y1)
        fmt.Println("2s :", x2, y2)
        child.Move(fyne.NewPos(x1, y1))
        child.Resize(cellSize)

        if g.horizontal() {
            if (i+1)%cols == 0 {
                row++
                col = 0
            } else {
                col++
            }
        } else {
            if (i+1)%cols == 0 {
                col++
                row = 0
            } else {
                row++
            }
        }
        i++
    }
    fmt.Println("i :", i)
}

func (g *adaptiveGridLayoutWithRatios) MinSize(objects []fyne.CanvasObject) fyne.Size {
    minSize := fyne.NewSize(0, 0)
    return minSize
}

func main() {
    myApp := app.New()
    myWindow := myApp.NewWindow("My Windows")
    myWindow.Resize(fyne.NewSize(600, 200))

    button1 := widget.NewButton("Button 1", func() {
        // Handle button click for button 1
    })

    button2 := widget.NewButton("Button 2", func() {
        // Handle button click for button 2
    })
    button1.Importance = widget.WarningImportance
    button2.Importance = widget.DangerImportance
    title := widget.NewLabelWithStyle("Custom", fyne.TextAlignCenter, fyne.TextStyle{Bold: true})

    myWindow.SetContent(container.NewVBox(title,
        NewAdaptiveGridWithRatios([]float32{0.3, 0.7}, button1, button2)))

    myWindow.ShowAndRun()
}

Ich möchte, dass die Schaltflächen nebeneinander mit einem relativen Breitenverhältnis von 3:7 platziert werden. Aber ich bekomme zwei horizontale Linien, eine unter der anderen. Ich ändere: https://github.com/fyne-io/fyne/blob/8c2509518b2df442a6b748d9b07754739592e6d7/layout/gridlayout.go Stellen Sie meine individuellen Produkte her.

Lösung

Das funktioniert:

package main

import (
    "fmt"
    "math"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/container"
    "fyne.io/fyne/v2/theme"
    "fyne.io/fyne/v2/widget"
)

func New(layout fyne.Layout, objects ...fyne.CanvasObject) *fyne.Container {
    return fyne.NewContainerWithLayout(layout, objects...)
}

func NewAdaptiveGridWithRatios(ratios []float32, objects ...fyne.CanvasObject) *fyne.Container {
    return New(NewAdaptiveGridLayoutWithRatios(ratios), objects...)
}

// Declare conformity with Layout interface
var _ fyne.Layout = (*adaptiveGridLayoutWithRatios)(nil)

type adaptiveGridLayoutWithRatios struct {
    ratios          []float32
    adapt, vertical bool
}

func NewAdaptiveGridLayoutWithRatios(ratios []float32) fyne.Layout {
    return &adaptiveGridLayoutWithRatios{ratios: ratios, adapt: true}
}

func (g *adaptiveGridLayoutWithRatios) horizontal() bool {
    if g.adapt {
        return fyne.IsHorizontal(fyne.CurrentDevice().Orientation())
    }

    return !g.vertical
}

func (g *adaptiveGridLayoutWithRatios) countRows(objects []fyne.CanvasObject) int {
    count := 0
    for _, child := range objects {
        if child.Visible() {
            count++
        }
    }

    return int(math.Ceil(float64(count) / float64(len(g.ratios))))
}

// Layout is called to pack all child objects into a specified size.
// For a GridLayout this will pack objects into a table format with the number
// of columns specified in our constructor.
func (g *adaptiveGridLayoutWithRatios) Layout(objects []fyne.CanvasObject, size fyne.Size) {

    rows := g.countRows(objects)
    cols := len(g.ratios)

    padWidth := float32(cols-1) * theme.Padding()
    padHeight := float32(rows-1) * theme.Padding()
    tGap := float64(padWidth)
    tcellWidth := float64(size.Width) - tGap
    cellHeight := float64(size.Height-padHeight) / float64(rows)

    fmt.Println(cols, rows)
    fmt.Println(cellHeight, tcellWidth+tGap, tGap)
    fmt.Println("tcellWidth, cellHeight", tcellWidth, cellHeight)
    if !g.horizontal() {
        padWidth, padHeight = padHeight, padWidth
        tcellWidth = float64(size.Width-padWidth) - tGap
        cellHeight = float64(size.Height-padHeight) / float64(cols)
    }

    row, col := 0, 0
    i := 0
    var x1, x2, y1, y2 float32 = 0.0, 0.0, 0.0, 0.0
    fmt.Println("padWidth, padHeight, tcellWidth, cellHeight, float32(theme.Padding()):", padWidth, padHeight, tcellWidth, cellHeight, float32(theme.Padding()))
    for _, child := range objects {
        if !child.Visible() {
            continue
        }

        if i == 0 {
            x1 = 0
            y1 = 0
        } else {
            x1 = x2 + float32(theme.Padding())*float32(1)
            y1 = y2 - float32(cellHeight)
        } // float32(tGap/float64(col))
        //  (size + float64(theme.Padding())) * float64(offset)  float32(theme.Padding())*float32(1)
        x2 = x1 + float32(tcellWidth*float64(g.ratios[i]))
        y2 = float32(cellHeight)

        fmt.Println("x1,y1 :", x1, y1)
        fmt.Println("x2, y2 :", x2, y2)
        fmt.Println("eff width", tcellWidth*float64(g.ratios[i]))

        fmt.Println("------")
        child.Move(fyne.NewPos(x1, y1))
        child.Resize(fyne.NewSize((x2 - x1), y2-y1))

        if g.horizontal() {
            if (i+1)%cols == 0 {
                row++
                col = 0
            } else {
                col++
            }
        } else {
            if (i+1)%cols == 0 {
                col++
                row = 0
            } else {
                row++
            }
        }
        i++
    }
    fmt.Println("i :", i)
}

func (g *adaptiveGridLayoutWithRatios) MinSize(objects []fyne.CanvasObject) fyne.Size {
    rows := g.countRows(objects)
    minSize := fyne.NewSize(0, 0)
    for _, child := range objects {
        if !child.Visible() {
            continue
        }

        minSize = minSize.Max(child.MinSize())
    }

    if g.horizontal() {
        minContentSize := fyne.NewSize(minSize.Width*float32(len(g.ratios)), minSize.Height*float32(rows))
        return minContentSize.Add(fyne.NewSize(theme.Padding()*fyne.Max(float32(len(g.ratios)-1), 0), theme.Padding()*fyne.Max(float32(rows-1), 0)))
    }

    minContentSize := fyne.NewSize(minSize.Width*float32(rows), minSize.Height*float32(len(g.ratios)))
    return minContentSize.Add(fyne.NewSize(theme.Padding()*fyne.Max(float32(rows-1), 0), theme.Padding()*fyne.Max(float32(len(g.ratios)-1), 0)))
}

func main() {
    myApp := app.New()
    myWindow := myApp.NewWindow("My Windows Custom UI")
    myWindow.Resize(fyne.NewSize(600, 200))

    var buttons [16]*widget.Button

    for i := 0; i < 16; i++ {
        button := widget.NewButton(fmt.Sprintf("Btn %d", i+1), func() {
            // Handle button click for this button
        })

        // Set the button importance based on the button index
        if i%2 == 0 {
            button.Importance = widget.WarningImportance
        } else {
            button.Importance = widget.DangerImportance
        }

        buttons[i] = button
    }

    pgBar := widget.NewLabelWithStyle("Progress :", fyne.TextAlignCenter, fyne.TextStyle{Italic: true})
    progressBar := widget.NewProgressBar()
    progressBar.SetValue(0.95)

    myWindow.SetContent(container.NewVBox(
        NewAdaptiveGridWithRatios([]float32{0.1, 0.4, 0.4, 0.1}, buttons[0], buttons[1], buttons[2], buttons[3]),
        NewAdaptiveGridWithRatios([]float32{0.2, 0.3, 0.1, 0.4}, buttons[4], buttons[5], buttons[6], buttons[7]),
        NewAdaptiveGridWithRatios([]float32{0.6, 0.1, 0.2, 0.1}, buttons[8], buttons[9], buttons[10], buttons[11]),
        NewAdaptiveGridWithRatios([]float32{0.1, 0.4, 0.4, 0.1}, buttons[12], buttons[13], buttons[14], buttons[15]),
        NewAdaptiveGridWithRatios([]float32{0.1, 0.9}, pgBar, progressBar),
    ))

    myWindow.ShowAndRun()
}

Ich habe mehrere Schaltflächen und andere Widgets in unterschiedlichen Proportionen hinzugefügt.

Das obige ist der detaillierte Inhalt vonPassen Sie das adaptive Rasterlayout von Fyne an. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen