⏱️ Timer e ProgressBar in Windows Forms
Crea applicazioni dinamiche che si aggiornano nel tempo!
🎯 Cosa Imparerai in Questa Lezione
Fino ad ora le tue app facevano qualcosa solo quando l’utente cliccava un pulsante.
Oggi scoprirai come creare applicazioni che si muovono da sole:
orologi che tic-taccano, cronometri che contano, barre di caricamento che si riempiono! ⏰🚀
Esegue codice automaticamente ogni tot millisecondi!
Perfetto per orologi, countdown, animazioni, controlli periodici.
Es: Ogni 1000ms (1 secondo) aggiorna l’ora corrente
Barra di progresso che si riempie! Mostra all’utente quanto manca
al completamento di un’operazione.
Es: Download file 0% ▱▱▱▱▱ → 100% ▰▰▰▰▰
Icona nella system tray (in basso a destra vicino all’orologio).
Per app che girano in background e notifiche.
Es: Promemoria che compare ogni 30 minuti
Prima di iniziare, dovresti aver completato:
- ✅ TabControl e DataGridView (Lezione 8)
- ✅ Gestione eventi
- ✅ Variabili e operazioni matematiche base
⏱️ Cos’è il Timer?
🤔 Analogia della Vita Reale
Hai presente la sveglia che suona ogni mattina alla stessa ora?
O il metronomo dei musicisti che fa “tic-tac” a ritmo costante?
Il Timer è esattamente questo: un componente che “suona” (esegue codice)
ogni tot tempo!
1️⃣ Imposti l’intervallo (es: 1000 millisecondi = 1 secondo)
2️⃣ Scrivi cosa deve fare nel metodo Timer_Tick
3️⃣ Avvii il Timer con timer.Start()
4️⃣ Il codice si ripete automaticamente ogni intervallo!
Interval: Tempo in millisecondi (1000 = 1 secondo)Enabled: true = attivo, false = fermo
🎮 Metodi Principali:
Start(): Avvia il timerStop(): Ferma il timer
Il Timer conta in millisecondi (ms), non secondi!
• 1000 ms = 1 secondo
• 500 ms = 0.5 secondi (mezzo secondo)
• 60000 ms = 60 secondi = 1 minuto
• 100 ms = 0.1 secondi (velocissimo!)
🕐 Esercizio 1: Orologio Digitale
▶ Obiettivo
Crea un orologio digitale che mostra l’ora corrente e si
aggiorna automaticamente ogni secondo! Come quello del computer ma nel TUO programma! 🕐
- Label:
lbl_ora- Text = “00:00:00”
- Font = Molto grande (es: Arial, 48pt, Bold)
- ForeColor = Colore che ti piace
- TextAlign = MiddleCenter
- Label:
lbl_data- Text = “01/01/2025”
- Font = Medio (es: Arial, 16pt)
- TextAlign = MiddleCenter
- Timer:
timer_orologio- Interval = 1000 (1 secondo)
- Enabled = true (si avvia automaticamente)
- Nella Toolbox cerca “Timer”
- Trascinalo sul form
- Appare in basso (non è visibile all’utente!)
- Imposta Properties → Interval = 1000
- Properties → Enabled = true
using System;
using System.Windows.Forms;
namespace OrologioDigitale
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// Imposta ora e data all'avvio
AggiornaOrario();
}
// ═══════════════════════════════════════════
// EVENTO TIMER: Si esegue ogni 1 secondo!
// ═══════════════════════════════════════════
private void timer_orologio_Tick(object sender, EventArgs e)
{
// Aggiorna l'orario
AggiornaOrario();
}
// ═══════════════════════════════════════════
// METODO: Aggiorna ora e data
// ═══════════════════════════════════════════
private void AggiornaOrario()
{
// Ottieni l'ora corrente
DateTime adesso = DateTime.Now;
// Formatta l'ora come HH:mm:ss (24 ore)
lbl_ora.Text = adesso.ToString("HH:mm:ss");
// Formatta la data come dd/MM/yyyy
lbl_data.Text = adesso.ToString("dddd, dd MMMM yyyy");
// BONUS: Cambia colore in base all'ora
int ora = adesso.Hour;
if (ora >= 6 && ora < 12)
{
// Mattino: Arancione
lbl_ora.ForeColor = Color.Orange;
}
else if (ora >= 12 && ora < 18)
{
// Pomeriggio: Blu
lbl_ora.ForeColor = Color.Blue;
}
else
{
// Sera/Notte: Viola
lbl_ora.ForeColor = Color.Purple;
}
}
}
}
- L'app si apre e mostra subito l'ora corrente
- Ogni 1 secondo il
timer_orologio_Tickviene chiamato automaticamente - Il metodo
AggiornaOrario()prende l'ora attuale e la mostra - Il colore cambia in base all'orario (mattino/pomeriggio/sera)
- Seleziona il Timer nella parte bassa del Designer
- Premi F4 per aprire Properties
- Clicca sull'icona del fulmine ⚡ (Eventi)
- Trova l'evento Tick
- Fai doppio click → Visual Studio crea il metodo
📚 Concetti Chiave - DateTime
DateTime adesso = DateTime.Now; Console.WriteLine(adesso.Hour); // 14 (ore) Console.WriteLine(adesso.Minute); // 30 (minuti) Console.WriteLine(adesso.Second); // 45 (secondi) Console.WriteLine(adesso.Day); // 15 (giorno) Console.WriteLine(adesso.Month); // 1 (gennaio) Console.WriteLine(adesso.Year); // 2025
DateTime dt = DateTime.Now;
dt.ToString("HH:mm:ss") // "14:30:45" (24 ore)
dt.ToString("hh:mm:ss tt") // "02:30:45 PM" (12 ore)
dt.ToString("dd/MM/yyyy") // "15/01/2025"
dt.ToString("dddd, dd MMMM yyyy") // "mercoledì, 15 gennaio 2025"
dt.ToString("yyyy-MM-dd") // "2025-01-15" (formato ISO)
timer.Start(); // Inizia a contare timer.Stop(); // Si ferma timer.Enabled = true; // Equivalente a Start() timer.Enabled = false; // Equivalente a Stop()
⏱️ Esercizio 2: Cronometro
▶ Obiettivo
Crea un cronometro con pulsanti Start, Stop e Reset!
Conta i secondi che passano e puoi fermarlo quando vuoi! ⏱️
- Label:
lbl_cronometro(Text = "00:00:00", Font grande) - Button:
btn_start(Text = "▶ Start") - Button:
btn_stop(Text = "⏸ Stop", Enabled = false) - Button:
btn_reset(Text = "🔄 Reset") - Timer:
timer_cronometro(Interval = 100, Enabled = false)
using System;
using System.Windows.Forms;
namespace Cronometro
{
public partial class Form1 : Form
{
// Variabile per tenere traccia dei millisecondi
private int millisecondi = 0;
public Form1()
{
InitializeComponent();
}
// ═══════════════════════════════════════════
// PULSANTE: START
// ═══════════════════════════════════════════
private void btn_start_Click(object sender, EventArgs e)
{
// Avvia il timer
timer_cronometro.Start();
// Disabilita Start, abilita Stop
btn_start.Enabled = false;
btn_stop.Enabled = true;
}
// ═══════════════════════════════════════════
// PULSANTE: STOP
// ═══════════════════════════════════════════
private void btn_stop_Click(object sender, EventArgs e)
{
// Ferma il timer
timer_cronometro.Stop();
// Abilita Start, disabilita Stop
btn_start.Enabled = true;
btn_stop.Enabled = false;
}
// ═══════════════════════════════════════════
// PULSANTE: RESET
// ═══════════════════════════════════════════
private void btn_reset_Click(object sender, EventArgs e)
{
// Ferma il timer
timer_cronometro.Stop();
// Resetta a zero
millisecondi = 0;
// Aggiorna display
AggiornaDisplay();
// Abilita Start, disabilita Stop
btn_start.Enabled = true;
btn_stop.Enabled = false;
}
// ═══════════════════════════════════════════
// TIMER TICK: Ogni 100ms (0.1 secondi)
// ═══════════════════════════════════════════
private void timer_cronometro_Tick(object sender, EventArgs e)
{
// Incrementa di 100 millisecondi
millisecondi += 100;
// Aggiorna il display
AggiornaDisplay();
}
// ═══════════════════════════════════════════
// AGGIORNA IL DISPLAY
// ═══════════════════════════════════════════
private void AggiornaDisplay()
{
// Converti millisecondi in ore:minuti:secondi
int totaleSecondi = millisecondi / 1000;
int ore = totaleSecondi / 3600;
int minuti = (totaleSecondi % 3600) / 60;
int secondi = totaleSecondi % 60;
int decimi = (millisecondi % 1000) / 100;
// Formatta come HH:MM:SS.d
lbl_cronometro.Text = string.Format("{0:00}:{1:00}:{2:00}.{3}",
ore, minuti, secondi, decimi);
}
}
}
- All'avvio: cronometro fermo a 00:00:00.0
- Clicchi Start → timer si avvia
- Ogni 0.1 secondi (100ms) → millisecondi += 100
- Il display si aggiorna: 00:00:00.1, 00:00:00.2, ... 00:00:01.0, ecc.
- Clicchi Stop → si ferma dove è arrivato
- Clicchi Reset → torna a 00:00:00.0
📚 Operazioni Matematiche Utili
10 % 3 = 1 // 10 diviso 3 = 3 con resto 1 15 % 4 = 3 // 15 diviso 4 = 3 con resto 3 100 % 60 = 40 // 100 secondi = 1 minuto e 40 secondi // Uso pratico: convertire secondi in minuti int totaleSecondi = 150; int minuti = totaleSecondi / 60; // 2 minuti int secondi = totaleSecondi % 60; // 30 secondi
int ore = 5, minuti = 7, secondi = 9;
// Senza Format (brutto)
string tempo = ore + ":" + minuti + ":" + secondi; // "5:7:9"
// Con Format e padding (bello!)
string tempo = string.Format("{0:00}:{1:00}:{2:00}", ore, minuti, secondi);
// Risultato: "05:07:09"
// {0:00} significa: prendi il primo parametro e mostralo con 2 cifre
📊 ProgressBar: Barra di Progresso
🤔 Cos'è la ProgressBar?
Hai presente quando installi un programma e vedi la barra che si riempie?
"Download in corso... 47% ▰▰▰▰▱▱▱▱▱▱" Quella è una ProgressBar!
Mostra visivamente quanto manca al completamento.
- Minimum: Valore minimo (di solito 0)
- Maximum: Valore massimo (es: 100 per percentuale)
- Value: Valore attuale (da Minimum a Maximum)
- Style: Blocks (a blocchi) o Continuous (continua)
Minimum = 0 Maximum = 100 Value = 47 Barra al 47%: ▰▰▰▰▰▱▱▱▱▱
🍅 Esercizio 3: Pomodoro Technique Timer
▶ Obiettivo
Crea un timer per la Pomodoro Technique: 25 minuti di lavoro,
poi 5 minuti di pausa. Con ProgressBar che mostra quanto manca! 🍅
Tecnica di produttività: lavori concentrato per 25 minuti,
poi ti premi con 5 minuti di pausa. Si ripete! Super efficace per studiare!
- Label:
lbl_stato(Text = "LAVORO", Font grande, Bold) - Label:
lbl_tempo(Text = "25:00", Font molto grande) - ProgressBar:
progressBar(Minimum = 0, Maximum = 100) - Button:
btn_start(Text = "▶ Inizia") - Button:
btn_pausa(Text = "⏸ Pausa", Enabled = false) - Button:
btn_reset(Text = "🔄 Reset") - Timer:
timer(Interval = 1000, Enabled = false)
using System;
using System.Drawing;
using System.Windows.Forms;
namespace PomodoroTimer
{
public partial class Form1 : Form
{
// Costanti (tempo in secondi)
private const int TEMPO_LAVORO = 25 * 60; // 25 minuti = 1500 secondi
private const int TEMPO_PAUSA = 5 * 60; // 5 minuti = 300 secondi
// Variabili di stato
private int secondiRimanenti;
private int secondiTotali;
private bool modalitaLavoro = true; // true = lavoro, false = pausa
public Form1()
{
InitializeComponent();
// Inizializza con modalità lavoro
ImpostaModalitaLavoro();
}
// ═══════════════════════════════════════════
// IMPOSTA MODALITÀ LAVORO
// ═══════════════════════════════════════════
private void ImpostaModalitaLavoro()
{
modalitaLavoro = true;
secondiRimanenti = TEMPO_LAVORO;
secondiTotali = TEMPO_LAVORO;
lbl_stato.Text = "⏰ TEMPO DI LAVORO";
lbl_stato.ForeColor = Color.Green;
this.BackColor = Color.LightGreen;
AggiornaDisplay();
}
// ═══════════════════════════════════════════
// IMPOSTA MODALITÀ PAUSA
// ═══════════════════════════════════════════
private void ImpostaModalitaPausa()
{
modalitaLavoro = false;
secondiRimanenti = TEMPO_PAUSA;
secondiTotali = TEMPO_PAUSA;
lbl_stato.Text = "☕ TEMPO DI PAUSA";
lbl_stato.ForeColor = Color.Blue;
this.BackColor = Color.LightBlue;
AggiornaDisplay();
}
// ═══════════════════════════════════════════
// PULSANTE: START
// ═══════════════════════════════════════════
private void btn_start_Click(object sender, EventArgs e)
{
timer.Start();
btn_start.Enabled = false;
btn_pausa.Enabled = true;
}
// ═══════════════════════════════════════════
// PULSANTE: PAUSA
// ═══════════════════════════════════════════
private void btn_pausa_Click(object sender, EventArgs e)
{
timer.Stop();
btn_start.Enabled = true;
btn_pausa.Enabled = false;
}
// ═══════════════════════════════════════════
// PULSANTE: RESET
// ═══════════════════════════════════════════
private void btn_reset_Click(object sender, EventArgs e)
{
timer.Stop();
ImpostaModalitaLavoro();
btn_start.Enabled = true;
btn_pausa.Enabled = false;
}
// ═══════════════════════════════════════════
// TIMER TICK: Ogni secondo
// ═══════════════════════════════════════════
private void timer_Tick(object sender, EventArgs e)
{
// Decrementa il tempo
secondiRimanenti--;
// Aggiorna il display
AggiornaDisplay();
// Controlla se è finito
if (secondiRimanenti <= 0)
{
timer.Stop();
// Suono di notifica
System.Media.SystemSounds.Beep.Play();
// Cambia modalità
if (modalitaLavoro)
{
// Finito il lavoro → inizia pausa
MessageBox.Show("⏰ Tempo scaduto!\n\nHai lavorato per 25 minuti.\nAdesso 5 minuti di pausa! ☕",
"Pomodoro",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
ImpostaModalitaPausa();
}
else
{
// Finita la pausa → inizia lavoro
MessageBox.Show("☕ Pausa finita!\n\nTorna al lavoro per altri 25 minuti! 💪",
"Pomodoro",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
ImpostaModalitaLavoro();
}
btn_start.Enabled = true;
btn_pausa.Enabled = false;
}
}
// ═══════════════════════════════════════════
// AGGIORNA DISPLAY
// ═══════════════════════════════════════════
private void AggiornaDisplay()
{
// Converti in minuti:secondi
int minuti = secondiRimanenti / 60;
int secondi = secondiRimanenti % 60;
// Mostra il tempo
lbl_tempo.Text = string.Format("{0:00}:{1:00}", minuti, secondi);
// Aggiorna la ProgressBar
// Calcola percentuale completata
int percentualeCompletata = (int)(((double)(secondiTotali - secondiRimanenti) / secondiTotali) * 100);
progressBar.Value = Math.Min(percentualeCompletata, 100);
// BONUS: Colore della progressbar in base al tempo rimasto
if (secondiRimanenti < 60)
{
// Ultimi 60 secondi → rosso (urgente!)
progressBar.ForeColor = Color.Red;
}
else if (secondiRimanenti < 300)
{
// Ultimi 5 minuti → arancione
progressBar.ForeColor = Color.Orange;
}
else
{
// Tanto tempo → verde
progressBar.ForeColor = Color.Green;
}
}
}
}
- App si apre in modalità LAVORO (sfondo verde, 25:00)
- Clicchi Inizia → il countdown parte
- La ProgressBar si riempie man mano
- Arriva a 00:00 → BEEP! MessageBox: "Tempo scaduto!"
- Passa in modalità PAUSA (sfondo blu, 05:00)
- Clicchi Inizia di nuovo → countdown pausa
- Arriva a 00:00 → BEEP! Torna in modalità LAVORO
- Il ciclo continua!
📚 Nuovi Concetti
// Suono beep standard SystemSounds.Beep.Play(); // Altri suoni disponibili: SystemSounds.Asterisk.Play(); // * SystemSounds.Exclamation.Play(); // ! SystemSounds.Hand.Play(); // ✋ SystemSounds.Question.Play(); // ?
int minore = Math.Min(5, 10); // 5 int maggiore = Math.Max(5, 10); // 10 // Uso pratico: limita un valore progressBar.Value = Math.Min(percentuale, 100); // Se percentuale = 150, Value sarà 100 (limite massimo)
// Dichiarazione costante private const int TEMPO_LAVORO = 1500; // Convenzione: NOME_TUTTO_MAIUSCOLO // Vantaggi: più leggibile, se cambi valore è in UN solo punto
📥 Esercizio 4: Simulatore Download
▶ Obiettivo
Simula il download di un file con ProgressBar che si riempie e percentuale che sale!
- ProgressBar:
progressBar - Label:
lbl_percentuale(Text = "0%") - Label:
lbl_stato(Text = "Pronto") - Button:
btn_download(Text = "📥 Scarica File") - Timer:
timer(Interval = 100, Enabled = false)
private int percentuale = 0;
private void btn_download_Click(object sender, EventArgs e)
{
// Reset
percentuale = 0;
progressBar.Value = 0;
lbl_stato.Text = "Download in corso...";
// Avvia timer
timer.Start();
// Disabilita pulsante
btn_download.Enabled = false;
}
private void timer_Tick(object sender, EventArgs e)
{
// Incrementa percentuale (random per simulare velocità variabile)
Random rnd = new Random();
int incremento = rnd.Next(1, 5); // Da 1 a 4
percentuale += incremento;
// Limita a 100
if (percentuale > 100)
percentuale = 100;
// Aggiorna UI
progressBar.Value = percentuale;
lbl_percentuale.Text = $"{percentuale}%";
// Download completato?
if (percentuale >= 100)
{
timer.Stop();
lbl_stato.Text = "✅ Download completato!";
lbl_stato.ForeColor = Color.Green;
btn_download.Enabled = true;
MessageBox.Show("File scaricato con successo!", "Completato",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
❓ Esercizio 5: Quiz a Tempo
▶ Obiettivo
Quiz con domande a risposta multipla. Hai 30 secondi per rispondere!
private int tempoRimasto = 30;
private int domandaCorrente = 0;
private int punteggioTotale = 0;
private string[] domande = {
"Quale linguaggio usiamo?",
"Quanti millisecondi in 1 secondo?",
"Che controllo mostra tabelle?"
};
private string[][] opzioni = {
new string[] { "C#", "Python", "Java", "Ruby" },
new string[] { "10", "100", "1000", "10000" },
new string[] { "Label", "TextBox", "DataGridView", "Button" }
};
private int[] risposteCorrette = { 0, 2, 2 }; // Indici delle risposte corrette
private void btn_inizia_Click(object sender, EventArgs e)
{
domandaCorrente = 0;
punteggioTotale = 0;
MostraDomanda();
}
private void MostraDomanda()
{
if (domandaCorrente >= domande.Length)
{
// Quiz finito!
timer.Stop();
MessageBox.Show($"Quiz completato!\nPunteggio: {punteggioTotale}/{domande.Length}",
"Fine", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
// Mostra domanda
lbl_domanda.Text = domande[domandaCorrente];
// Mostra opzioni (4 RadioButton)
rdb_opzione1.Text = opzioni[domandaCorrente][0];
rdb_opzione2.Text = opzioni[domandaCorrente][1];
rdb_opzione3.Text = opzioni[domandaCorrente][2];
rdb_opzione4.Text = opzioni[domandaCorrente][3];
// Reset timer
tempoRimasto = 30;
progressBar.Maximum = 30;
progressBar.Value = 30;
timer.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
tempoRimasto--;
progressBar.Value = tempoRimasto;
lbl_tempo.Text = $"Tempo: {tempoRimasto}s";
if (tempoRimasto <= 0)
{
timer.Stop();
MessageBox.Show("Tempo scaduto!", "Oops",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
domandaCorrente++;
MostraDomanda();
}
}
private void btn_risposta_Click(object sender, EventArgs e)
{
timer.Stop();
// Controlla quale RadioButton è selezionato
int rispostaData = -1;
if (rdb_opzione1.Checked) rispostaData = 0;
else if (rdb_opzione2.Checked) rispostaData = 1;
else if (rdb_opzione3.Checked) rispostaData = 2;
else if (rdb_opzione4.Checked) rispostaData = 3;
// Verifica correttezza
if (rispostaData == risposteCorrette[domandaCorrente])
{
punteggioTotale++;
MessageBox.Show("✅ Risposta corretta!", "Bravo!",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("❌ Risposta sbagliata!", "Oops",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
domandaCorrente++;
MostraDomanda();
}
🎓 Riepilogo: Cosa Hai Imparato
- Eseguire codice periodicamente
- Creare orologi e cronometri
- Start(), Stop(), Interval
- Mostrare avanzamento
- Feedback visivo operazioni
- Minimum, Maximum, Value
- Ottenere data/ora corrente
- Formattare orari
- Calcoli con tempo
- Countdown e timer
- Simulazioni real-time
- Quiz interattivi
Hai imparato a creare app dinamiche! Nella prossima lezione scoprirai come
creare applicazioni multi-finestra: form di login che aprono
dashboard, finestre di dettaglio, dialog personalizzati! 🪟