Skip to content

Table

This is a table widget in Fyne used to display data in rows and columns.

Show Code
package main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
func main() {
myApp := app.New()
w := myApp.NewWindow("Table with Headers")
// Sample data
headers := []string{"Category", "Item", "Quantity"}
data := [][]string{
{"Fruits", "Apples", "10"},
{"Fruits", "Bananas", "25"},
{"Vegetables", "Carrots", "12"},
{"Vegetables", "Spinach", "7"},
{"Grains", "Rice", "50"},
}
// Table has headers + data (rows+1)
table := widget.NewTable(
func() (int, int) {
return len(data) + 1, len(headers) // +1 for header row
},
func() fyne.CanvasObject {
return widget.NewLabel("placeholder")
},
func(id widget.TableCellID, cell fyne.CanvasObject) {
label := cell.(*widget.Label)
if id.Row == 0 {
// Header row
label.SetText(headers[id.Col])
label.TextStyle = fyne.TextStyle{Bold: true}
} else {
// Data rows
label.SetText(data[id.Row-1][id.Col])
label.TextStyle = fyne.TextStyle{}
}
},
)
table.SetColumnWidth(0, 100)
table.SetColumnWidth(1, 120)
table.SetColumnWidth(2, 80)
content := container.NewStack(table)
w.SetContent(content)
w.Resize(fyne.NewSize(350, 250))
w.ShowAndRun()
}

This Demostrates the power of tables by creating a complete CRUD APP. The app allows people Add, Delete and Update items in real-time.

Show Code
package main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/widget"
)
type Item struct {
Name string
Category string
Quantity string
}
func main() {
myApp := app.New()
w := myApp.NewWindow("CRUD Table")
// Initial data
data := []Item{
{"Apples", "Fruit", "10"},
{"Bananas", "Fruit", "20"},
{"Carrots", "Vegetable", "15"},
}
// Table reference for refreshing it
var table *widget.Table
// Refresh function
refreshTable := func() {
table.Refresh()
}
// Define table
table = widget.NewTable(
func() (int, int) {
return len(data) + 1, 4 // +1 for headers
},
func() fyne.CanvasObject {
// Each cell is wrapped in padding so we can add spacing
return container.NewPadded(widget.NewLabel(""))
},
func(id widget.TableCellID, obj fyne.CanvasObject) {
cell := obj.(*fyne.Container)
cell.Objects = nil // reset container
if id.Row == 0 { // header row
headers := []string{"Name", "Category", "Quantity", "Actions"}
lbl := widget.NewLabel(headers[id.Col])
lbl.TextStyle = fyne.TextStyle{Bold: true}
cell.Add(lbl)
} else {
row := id.Row - 1
switch id.Col {
case 0:
cell.Add(widget.NewLabel(data[row].Name))
case 1:
cell.Add(widget.NewLabel(data[row].Category))
case 2:
cell.Add(widget.NewLabel(data[row].Quantity))
case 3:
editBtn := widget.NewButton("Edit", func() {
showEditDialog(w, &data[row], refreshTable)
})
deleteBtn := widget.NewButton("Delete", func() {
data = append(data[:row], data[row+1:]...)
refreshTable()
})
// Add spacing between buttons
cell.Add(container.NewHBox(
editBtn,
widget.NewLabel(" "),
deleteBtn,
))
}
}
},
)
table.SetColumnWidth(0, 100)
table.SetColumnWidth(1, 120)
table.SetColumnWidth(2, 80)
// Add new item button
addBtn := widget.NewButton("Add Item", func() {
showAddDialog(w, &data, refreshTable)
})
content := container.NewBorder(addBtn, nil, nil, nil, table)
w.SetContent(content)
w.Resize(fyne.NewSize(600, 400))
w.ShowAndRun()
}
// a function to add items
func showAddDialog(win fyne.Window, data *[]Item, refresh func()) {
nameEntry := widget.NewEntry()
categoryEntry := widget.NewEntry()
quantityEntry := widget.NewEntry()
form := &widget.Form{
Items: []*widget.FormItem{
{Text: "Name", Widget: nameEntry},
{Text: "Category", Widget: categoryEntry},
{Text: "Quantity", Widget: quantityEntry},
},
OnSubmit: func() {
*data = append(*data, Item{
Name: nameEntry.Text,
Category: categoryEntry.Text,
Quantity: quantityEntry.Text,
})
refresh()
win.Canvas().Overlays().Top().Hide()
},
}
d := dialog.NewCustom("Add Item", "Close", form, win)
d.Resize(fyne.NewSize(400, 250))
d.Show()
}
// a function to edit items
func showEditDialog(win fyne.Window, item *Item, refresh func()) {
nameEntry := widget.NewEntry()
nameEntry.SetText(item.Name)
categoryEntry := widget.NewEntry()
categoryEntry.SetText(item.Category)
quantityEntry := widget.NewEntry()
quantityEntry.SetText(item.Quantity)
form := &widget.Form{
Items: []*widget.FormItem{
{Text: "Name", Widget: nameEntry},
{Text: "Category", Widget: categoryEntry},
{Text: "Quantity", Widget: quantityEntry},
},
OnSubmit: func() {
item.Name = nameEntry.Text
item.Category = categoryEntry.Text
item.Quantity = quantityEntry.Text
refresh()
win.Canvas().Overlays().Top().Hide()
},
}
d := dialog.NewCustom("Edit Item", "Close", form, win)
d.Resize(fyne.NewSize(400, 250))
d.Show()
}