Maison  >  Article  >  développement back-end  >  Personnaliser la disposition de la grille adaptative Fyne

Personnaliser la disposition de la grille adaptative Fyne

PHPz
PHPzavant
2024-02-12 15:30:07919parcourir

自定义 Fyne 自适应网格布局

Contenu de la question

Je modifie le conteneur.newadaptivegrid() de la bibliothèque fyne pour restituer la largeur du widget en fonction des tranches proportionnelles que nous passons. À partir de maintenant, containers.newadaptivegrid() restitue des widgets de largeur égale dans une rangée. Fondamentalement (taille totale des lignes / widgets maintenant).

Mon 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()
}

Je souhaite que les boutons soient placés côte à côte avec un rapport de largeur relative de 3:7. Mais j'obtiens deux lignes horizontales, l'une en dessous de l'autre. Je modifie : https://github.com/fyne-io/fyne/blob/8c2509518b2df442a6b748d9b07754739592e6d7/layout/gridlayout.go Fabriquer mes produits personnalisés.

Solution

Cela fonctionne :

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()
}

J'ai ajouté plusieurs boutons et autres widgets dans des proportions différentes.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer