Skip to content

Template Starter — Progetto Flet

  1. Copia questo file come main.py nella cartella del progetto
  2. Modifica la parte # --- QUI LA TUA APP ---
  3. Esegui con python main.py
"""
Template base per progetto Flet
===============================
Include:
- Setup pagina
- Caricamento e salvataggio JSON
- SnackBar di feedback
- Tema chiaro/scuro
- Navigazione base
"""
import flet as ft
import json
import os
import datetime
# === CONFIGURAZIONE ===
TITOLO_APP = "La Mia App"
FILE_DATI = "dati.json"
VERSIONE = "1.0"
# === UTILITY DATI ===
def carica_dati():
"""Carica i dati dal file JSON. Se non esiste, ritorna lista vuota."""
try:
if os.path.exists(FILE_DATI):
with open(FILE_DATI, "r", encoding="utf-8") as f:
return json.load(f)
except json.JSONDecodeError:
print("File dati danneggiato, ricreo...")
return []
def salva_dati(dati):
"""Salva i dati su file JSON."""
try:
# Salva prima su file temporaneo, poi rinomina (operazione atomica)
temp = FILE_DATI + ".tmp"
with open(temp, "w", encoding="utf-8") as f:
json.dump(dati, f, indent=2, ensure_ascii=False)
os.replace(temp, FILE_DATI)
return True
except Exception as ex:
print(f"Errore salvataggio: {ex}")
return False
# === UTILITY UI ===
def mostra_snack(page, messaggio, colore="green", durata=3000):
"""Mostra una notifica temporanea in basso."""
page.snack_bar = ft.SnackBar(
content=ft.Text(messaggio),
open=True,
bgcolor=colore,
duration=durata,
)
page.update()
def conferma_elimina(page, messaggio, funzione_conferma):
"""Mostra un dialogo di conferma."""
def on_confirm(e):
dialog.open = False
funzione_conferma()
page.update()
def on_cancel(e):
dialog.open = False
page.update()
dialog = ft.AlertDialog(
title=ft.Text("Conferma"),
content=ft.Text(messaggio),
actions=[
ft.TextButton("Annulla", on_click=on_cancel),
ft.ElevatedButton("Elimina", on_click=on_confirm, color="red"),
],
actions_alignment=ft.MainAxisAlignment.END,
)
page.dialog = dialog
dialog.open = True
page.update()
def today():
"""Ritorna la data odierna come stringa YYYY-MM-DD."""
return datetime.date.today().isoformat()
# === MAIN APP ===
def main(page: ft.Page):
# --- CONFIGURAZIONE PAGINA ---
page.title = TITOLO_APP
page.padding = 20
page.scroll = ft.ScrollMode.AUTO
page.theme_mode = ft.ThemeMode.LIGHT
# Tema personalizzato
page.theme = ft.Theme(
color_scheme=ft.ColorScheme(
primary="blue",
secondary="amber",
)
)
# --- STATO ---
dati = carica_dati()
contenuto_principale = ft.Column(spacing=10, expand=True)
# --- FUNZIONI APP ---
def ricostruisci_ui():
"""Ricostruisce la UI partendo da 'dati'."""
contenuto_principale.controls.clear()
if not dati:
contenuto_principale.controls.append(
ft.Container(
content=ft.Column([
ft.Icon(ft.icons.INFO_OUTLINE, size=50, color="grey"),
ft.Text("Nessun elemento presente", color="grey", italic=True),
ft.Text("Aggiungine uno usando il form sopra!", color="grey", size=14),
], horizontal_alignment=ft.CrossAxisAlignment.CENTER),
padding=40,
)
)
page.update()
return
for i, elem in enumerate(dati):
# --- PERSONALIZZA QUI IL CONTENUTO DI OGNI ELEMENTO ---
card = ft.Container(
content=ft.Row([
ft.Column([
ft.Text(
elem.get("titolo", f"Elemento {i+1}"),
weight="bold", size=16
),
ft.Text(
elem.get("data", ""),
color="grey", size=12
),
], expand=True),
ft.Row([
ft.IconButton(
ft.icons.EDIT, icon_color="blue",
on_click=lambda e, idx=i: modifica_elemento(idx)
),
ft.IconButton(
ft.icons.DELETE, icon_color="red",
on_click=lambda e, idx=i: elimina_elemento(idx)
),
]),
]),
padding=15,
bgcolor="white",
border_radius=12,
shadow=ft.BoxShadow(
blur_radius=8,
color=ft.colors.with_opacity(0.15, "black"),
),
)
contenuto_principale.controls.append(card)
page.update()
def aggiungi_elemento(e):
"""Aggiunge un nuovo elemento."""
# --- PERSONALIZZA QUI LA LOGICA DI AGGIUNTA ---
pass
def modifica_elemento(idx):
"""Modifica un elemento esistente."""
# --- PERSONALIZZA QUI LA LOGICA DI MODIFICA ---
mostra_snack(page, "✏️ Modifica in sviluppo...", "blue")
pass
def elimina_elemento(idx):
"""Elimina un elemento dopo conferma."""
def conferma():
nonlocal dati
elem = dati.pop(idx)
salva_dati(dati)
ricostruisci_ui()
mostra_snack(page, f"🗑️ '{elem.get('titolo', 'elemento')}' eliminato!", "orange")
elem_nome = dati[idx].get("titolo", "elemento")
conferma_elimina(page, f"Eliminare '{elem_nome}'?", conferma)
# --- INTERFACCIA ---
# Barra superiore
def cambia_tema(e):
page.theme_mode = ft.ThemeMode.DARK if page.theme_mode == ft.ThemeMode.LIGHT else ft.ThemeMode.LIGHT
page.update()
page.add(
ft.Row([
ft.Text(f"📱 {TITOLO_APP}", size=24, weight="bold", expand=True),
ft.IconButton(ft.icons.DARK_MODE, on_click=cambia_tema, tooltip="Cambia tema"),
]),
ft.Divider(),
# --- QUI LA TUA APP ---
# Esempio: form di input
# ft.Row([input_campo, ft.ElevatedButton("Aggiungi", on_click=aggiungi_elemento)]),
ft.Divider(),
# Contatore elementi
ft.Text(f"Elementi: {len(dati)}", color="grey", size=14),
contenuto_principale,
)
# Mostra dati all'avvio
ricostruisci_ui()
# === AVVIO ===
if __name__ == "__main__":
ft.app(target=main)
Cosa modificareDove
Nome appTITOLO_APP = "..."
File datiFILE_DATI = "..."
Colore temaprimary="..." nel color_scheme
Form di inputSotto # --- QUI LA TUA APP ---
Contenuto cardIn ricostruisci_ui() nella sezione # --- PERSONALIZZA QUI
Logica aggiuntaIn aggiungi_elemento()
Logica modificaIn modifica_elemento()