Con o senza sconto?
Cerchiamo di realizzare il programma che gestisca gli sconti per la nota catena di supermercati Conrad: fornito dall'utente l'importo dello scontrino, applicare (oppure no) uno sconto del 5%. Il programma dovrà quindi verificare la presenza dello sconto: se deve essere applicato si eseguirà il calcolo, altrimenti... niente. L'utente può indicare al programma la presenza dello sconto tramite un apposito pulsante che permetta di essere spuntato. Il suo scopo è lontano dallo scopo di un normale pulsante: nel momento in cui si preme non si vuole eseguire un'azione ma solo mettere la spunta (se prima non ci fosse stata) oppure toglierla (se al momento del click fosse già presente). Nel momento in cui l'utente premerà l'effettivo pulsante per avviare l'elaborazione, il programma andrà a verificare se il pulsante di spunta è – appunto – spuntato o meno.
Il pulsante di spunta si chiama – in JavaFX – CheckBox e viene dichiarato allo stesso modo degli altri oggetti grafici, quindi:
CheckBox scontoPresente = new CheckBox();
Dove inserisci tale dichiarazione? Così nel metodo start():
public class Sconto extends Application { @Override public void start(Stage primaryStage) { CheckBox scontoPresente = new CheckBox();
Oppure così direttamente nella classe fuori dai qualsiasi metodo?
public class Sconto extends Application { CheckBox scontoPresente = new CheckBox(); @Override public void start(Stage primaryStage) {
La scelta giusta è di inserirlo al livello di classe (fuori dai metodi) perché con quest'oggetto il programma interagirà sia al momento della sua disposizione nella finestra sia nel momento in cui l'utente avvia il calcolo, quindi alla pressione del pulsante.
Nel metodo start() inseriremo anche il testo che dovrà visualizzare in quanto per ora comparirebbe il solo quadratino senza alcunché di spiegazione. La tecnica per impostare il testo di un oggetto è sempre la stessa: usare il metodo setText("testo") che nel nostro esempio sarà:
scontoPresente.setText("applica sconto");
In alternativa potremmo usare il sistema più compatto che fa indicare il testo direttamente alla costruzione dell'oggetto:
CheckBox scontoPresente = new CheckBox("applica sconto");
La funzione che andremo a scrivere non appena verrà premuto il pulsante di avvio al calcolo si
dovrà chiedere se c'è la spunta sullo sconto. In caso affermativo toglie il 5% dalla quantità indicata
altrimenti la cifra spesa rimarrà immutata. Osserva che il programma non sa a priori, cioè nel momento
in cui tu lo stai scrivendo, se ci sarà o no lo sconto; serve quindi che tutte le istruzioni del calcolo
siano eseguite solo ed esclusivamente se tale fatto sarà verificato. Per questo si utilizza l'istruzione if
,
in italiano SE. La logica di funzionamento è la seguente:
che applicato all'esempio in questione diviene
Se quanto sopra scritto in italiano è chiaro puoi passare direttamente alla versione Java che è pari pari quello sopra riportato a meno della scrittura nello specifico linguaggio:
if( scontoPresente.isSelecteded() ) { //fai il calcolo dello sconto //sottrai lo sconto dal costo }
Saltano subito all'occhio alcune cose sulla if
ed una sulla spunta. Cominciamo da quest'ultima:
il metodo isSelected()
vale vero se è visuazzata la spunta, altrimenti varrà falso;
questo vuol dire che la parte contenuta nelle parentesi tonde letteralmente la puoi leggere così:
"c'è la spunta sull'oggetto scontoPresente". Passiamo all'if: il fatto da verificare è sempre racchiuso
nelle parentesi tonde. Dell'espressione che qui si va a scrivere si dovrà sempre poter dire se questa
è vera o falsa; nell'esempio infatti si dice che scontoPresente è spuntato, tale espressione
diciamo che è vera se in effetti la spunta c'è altrimenti è falsa.
L'espressione che deve essere valutata da if si chiama condizione e – come detto – è sempre racchiusa tra parentesi tonde. A seguire osservi delle parentesi graffe: proprio come quando hai scritto le tue funzioni, le graffe racchiudono una sequenza di istruzioni. Nel nostro caso raccoglieranno tutte e sole quelle istruzioni che dovranno essere eseguite nel caso in cui la condizione è vera. Ciò vuol dire che se invece la condizione è falsa, ossia non c'è la spunta, tali istruzioni non vanno eseguite.
Il programma, in definitiva e a meno delle importazioni di rito è il seguente:
public class Sconto extends Application { TextField scontrino = new TextField(); CheckBox scontoPresente = new CheckBox(); TextField daPagare = new TextField(); @Override public void start(Stage primaryStage) { Button sconta = new Button(); Text l_scontrino = new Text(); Text l_daPagare = new Text(); sconta.setText("Verifica e sconta"); scontoPresente.setText("Diritto allo sconto del 5%"); l_scontrino.setText("Scontrino €"); l_daPagare.setText("A pagare €"); sconta.setOnAction(e -> calcolaSconto() ); GridPane pannello = new GridPane(); pannello.setHgap(10); pannello.setVgap(7); pannello.add(l_scontrino, 0, 0); pannello.add(scontrino, 1, 0); pannello.add(sconta, 0, 1); pannello.add(scontoPresente, 1, 1); pannello.add(l_daPagare, 0, 2); pannello.add(daPagare, 1, 2); Scene scene = new Scene(pannello, 350, 200); primaryStage.setScene(scene); primaryStage.setTitle("Valuta lo sconto"); primaryStage.show(); } public void calcolaSconto() { int soldi, sconto; soldi=Integer.parseInt(scontrino.getText()); if(scontoPresente.isSelected()) { sconto = soldi * 5 / 100; soldi = soldi - sconto; } daPagare.setText ("" + soldi); } public static void main(String[] args) { launch(args); } }
if
A questo punto introduciamo formalmente l'istruzione if:
L'istruzione if è composta da 3 parti: una condizione, un corpo_if e un corpo_else secondo la sintassi:if( condizione ){ corpo_if; } else { corpo_else; }La condizione è una espressione booleana, se vale true implicherà l'esecuzione del corpo_if e se vale false l'esecuzione del corpo_else. La parte else con relativo corpo è opzionale.
Da notare che verrà eseguito il corpo_if o corpo_else e mai entrambe e che la parte else non ha una condizione perché il corpo_else viene eseguito se la condizione dell'if risulta falsa, non c'è bisogno di scrivere una ulteriore condizione. Una cosa che potrebbe non sembrare ovvia: all'interno del corpo dell'if o dell'else potremmo trovare nuovamente un if.
Quanto vale y alla fine di questo frammento di programma?
int x=7; int y=0; if(x<5){ y=3; }else{ if(x>=2){ y=1; }else{ y=2; } }0no, il valore della y viene modificato 1 2no, giustamente si va nella parte else dell'if esterno ma poi... 3no, x non è minore di 5
Espressioni booleane
Nell'esempio precedente abbiamo usato come condizione lo stato di un pulsante
(selezionato oppure no) ma questa è soltanto una possibilità.
Possiamo utilizzare una qualsiasi espressione di cui sia possibile
dire se è vera o falsa (attenzione, il "vero/falso" non ha nulla a che fare con il "corretto/sbagliato"):
queste espressioni si chiamano "espressioni booleane"
e in Java e il loro valore può essere soltanto true o false con il significato che
è facile immaginare. Ad esempio l'espressione 4<2
vale false
mentre 3<7
vale true
.
Una espressione booleana si può ottenere sia combinando valori numerici che combinando valori booleani, andiamo avanti con ordine.
Operatori di confronto
Gli operatori di confronto hanno come argomento due valori numerici (ad eccezione di uguale e diverso che operano anche su operandi boolean) e restituiscono come risultato un valore boolean.
- ==
- a == b
a è uguale a b, vale true se a ha lo stesso valore di b - !=
- a != b
a è diverso da b, vale true se a non ha lo stesso valore di b - >
- a > b
a è maggiore di b, vale true se a è maggiore a b - >=
- a >= b
a è maggiore o uguale a b, vale true se a è maggiore o uguale a b - <
- a < b
a è minore di b, vale true se a è minore di b - <=
- a <= b
a è minore o uguale a b, vale true se a è minore o uguale a b
Volume del cubo
Poniamo per esempio di voler realizzare un programma che calcoli il volume di un cubo a patto che l'utente non inserisca un valore negativo come misura del lato. Il nostro programma ha una casella di testo che si chiama cLato in cui l'utente inserirà la misura del lato e una etichetta che si chiama eVolume in cui visualizzeremo il risultato. Se l'utente scriverà un numero negativo nell'etichetta scriveremo "errore: lato negativo".
public void calcolaVolume(){ String testoLato = cLato.getText(); int lato = Integer.parseInt(testoLato); int volume; if( lato < 0 ){ eVolume.setText("errore: lato negativo"); } else { volume = lato * lato * lato; eVolume.setText(""+volume); } }
In questo caso l'espressione booleana è lato < 0
che varrà
true se ad esempio il lato è lungo "-7" e false se ad esempio il lato misura "8".
Per esercizio costruisci il programma e verificane il funzionamento.
Pari o dispari?
Matematica: dato un numero, dire se questi è pari o dispari. È noto che per essere pari è necessario che sia divisibile per 2. Detto così sembra di difficile soluzione: ci chiediamo allora quando un numero è divisibile per 2 e la risposta sarà: un numero è divisibile per 2 se il resto della divisione (stiamo parlando di divisione tra numeri interi) è 0, altrimenti non è divisibile per 2, quindi non è pari e cioè è dispari:
La parte else in un condizionale...
è obbligatoriano, può essere omessa deve specificare la condizione contraria dell'ifno, l'else non ha una condizione: viene eseguita se la condizione dell'if è falsa è opzionaleIn Java per calcolare il resto si usa l'operatore %. Ad esempio 17%10 dà come risultato 7, 8%3 dà come risultato 2 e 55%5 dà come risultato 0. Bene. Posto di aver già realizzato la funzione start(), scriviamo qui la funzione del calcolo:
public void verificaPari() { int num; num = Integer.parseInt(numero.getText()); //numero è il nome della TextBox con il dato di input if(num%2 == 0) { messaggio.setText("il numero è pari"); //messaggio è il nome della Label per la risposta } else { messaggio.setText("il numero è dispari"); } }
Operatori logici
Servono ad esprimere fatti abbastanza comuni come ad esempio: "un voto è un numero maggiore di zero e minore o uguale a dieci", hanno come operandi dei valori booleani e come risultato un valore booleano.
- ||
- or, "oppure". Vale true se uno dei due operandi è true.
|| true false true true true false true false true || false
valetrue
- &&
- and, "e". Vale true se entrambe i due operandi sono true.
&& true false true true false false false false true && false
valefalse
- !
- not, "non". Inverte il valore di verità che lo segue, lavora su un singolo operando.
! true false false true !true
valefalse
Sembrano complicati? Proviamo a scrivere il programma che controlla se un valore inserito è un possibile voto o meno, il dato lo leggiamo dalla casella cVoto e il risultato lo scriviamo in eRisposta:
public void controllaVoto(){ String testoVoto = cvoto.getText(); int voto = Integer.parseInt(testoVoto); if( voto>0 && voto<=10 ){ eVolume.setText(voto + " è un voto"); } else { volume = lato * lato * lato; eVolume.setText(voto + " non è un voto"); } }
Quanto vale l'espressione voto>0 && voto<=10
se voto vale 8?
Quanto vale l'espressione voto<1 || voto>10
se voto vale 8?
Quale delle seguenti espressioni è di tipo boolean?
4+5no, il risultato è 9 che è unint
3**7no, non ha un tipo perché è sbagliata
4>3si, per la precisione vale true
In Java gli operatori logici vengono valutati con una tecnica chiamata "a corto circuito"
o "valutazione minima" che sta a significare che se l'operando sinistro è sufficiente per stabilire il
risultato l'altro non viene neanche valutato. Prendiamo per esempio l'espressione
4==2+2 || 78==12
visto che 4==2+2
è vera e che per l'operatore
or se un operando vale true anche il risultato vale true la parte 78==12
non viene neanche considerata.
Radio
La casella di spunta si adopera in genere per attivare o meno una certa opzione.
Caso diverso invece è il bisogno di fornire all'utente una rosa di possibilità tra cui poterne
scegliere esattamente una. Questo significa che quando si apre il programma una scelta
deve essere già impostata e sarà poi l'utente – eventualemente – a modificarla.
La soluzione è l'uso dei pulsanti radio (RadioButton
in JavaFX).
L'esempio classico è maschio o femmina: ogni utente apparterrà al primo od al secondo caso;
il programma, al momento della visualizzazione ( in start() ),
può proporre maschio e poi eventualmente chi lo usa lo cambierà.
Modifichiamo il programma di saluto visto nelle prime sezioni in modo tale che dia
un messaggio diverso a seconda che chi lo sta usando è maschio o femmina.
Innanzi tutto la dichiarazione è ormai intuitiva
(RadioButton nomePulsante = new RadioButton()
),
così come il metodo per impostarne il testo (
nomePulsante.setText("testo da visualizzare")
) e quello per
verificare se un dato pulsante radio è selezionato (nomePulsante.isSelected()
).
Va invece detto che per impostare una selezione su di un pulsante radio si usa il metodo
setSelected()
e nelle parentesi va indicato true (vero) o false (falso) la presenza della scelta;
in altre parole se il pulsante lo vogliamo selezionato scriveremo nomePulsante.setSelected(true)
e per averlo non selezionato scriveremo nomePulsante.setSelected(false)
e – nota bene – quest'ultimo
metodo vale pari anche per le CheckBox
; puoi quindi mettere o togliere spunte direttamente da
programma come meglio credi. Passiamo finalmente al codice:
TextField nome = new TextField(); RadioButton maschio = new RadioButton(); RadioButton femmina = new RadioButton(); TextField saluto = new TextField(); @Override public void start(Stage primaryStage) { Button dimmiCiao = new Button(); ToggleGroup genere = new ToggleGroup(); Label lNome = new Label(); Label lSaluto = new Label(); dimmiCiao.setText("Ti voglio salutare"); maschio.setText("Maschio"); femmina.setText("Femmina"); maschio.setToggleGroup(genere); femmina.setToggleGroup(genere); maschio.setSelected(true); lNome.setText("Ti chiami"); lSaluto.setText("Dirò"); dimmiCiao.setOnAction( e -> saluta() ); GridPane pannello = new GridPane(); pannello.setHgap(10); pannello.setVgap(7); pannello.add(lNome, 0, 0); pannello.add(nome, 1, 0); pannello.add(maschio, 0, 1); pannello.add(femmina, 1, 1); pannello.add(dimmiCiao, 0, 2); pannello.add(lSaluto, 0, 3); pannello.add(saluto, 1, 3); Scene scene = new Scene(pannello, 550, 200); primaryStage.setTitle("Ancora saluti..."); primaryStage.setScene(scene); primaryStage.show(); } public void saluta(){ if(maschio.isSelected()){ saluto.setText ("Egregio sig. " + nome.getText() + " benvenuto!"); } else { saluto.setText ("Gentile sig.ra " + nome.getText() + " benvenuta!"); } }
Come si controlla la presenza della spunta su una casella CheckBox?
usando il metodo check()questo metodo non esiste per l'oggetto CheckBox usando i metodo add()questo metodo si usa per aggiungere un elemento ad esempio ad un GridPane usando il metodo isSelected() usando il metodo setScene()questo metodo si usa ad per aggiungere la scena ad un oggetto StageUn'ultima questione nel programma appena scritto che sicuramente avrai già osservato:
l'oggetto ToggleGroup
. In una finestra ci possono essere vari gruppi di pulsanti radio,
ad esempio uno indica il genere (maschio/femmina) ed un altro l'essere maggiorenne/minorenne.
È per noi intuitivo che l'essere maschio o femmina porta alla selezione di una delle due possibilità e non
ha alcuna influenza sull'altra scelta, quella della maggiore età; non è ovvio però per il computer che quindi
non sa quali sono i pulsanti legati da un senso logico e quali sono invece indipendenti.
Per questo si crea un gruppo di pulsanti e poi si dice ai singoli pulsanti a quale gruppo appartengono,
in ogni gruppo soltanto un pulsante può essere selezionato (es: se si seleziona "femmina" maschio viene automaticamente
deselezionato). Se ci sono più gruppi si dichiarano più oggetti
ToggleGroup
e ciascun pulsante radio andrà legato al proprio gruppo.
Per legare un pulsante radio ad un gruppo è sufficiente usare il metodo setToggleGroup()
in questo modo:
nomePulsanteRadio.setToggleGroup(nomeGruppo);
Esercizio: il fantomatico dott. Finger ha inventato la formula per calcolare il peso ideale a partire dall'altezza, dal genere (maschio o femmina) e dalla corporatura: prima si calcola l'altezza divisa per 60 nel caso in cui si pratica attività sportiva, altrimenti l'altezza va divisa per 120. La quantità così ottenuta la chiameremo a. Si riprende poi l'altezza e si toglie 100 nel caso in cui è un uomo o si toglie 112 nel caso in cui è una donna. Il risultato lo chiameremo b. Indicheremo ora l'indice di Finger (e lo chiameremo iFinger) il risultato della somma tra le quantità a e b. Il peso ideale si ottiene – in fine – dividendo l'indice di Finger per 1,1 se la corporatura è piccola; per 0,95 se la corporatura è grande mentre nulla si fa (equivarrebbe a dividere per 1) per la normale corporatura.
Esercizio: Scrivi un programma che al suo avvio estrae un numero casuale e poi chiede all'utente di indovinare il numero estratto. Se l'utente non indovina il programma deve dire se il numero estratto è più grande o più piccolo.
Il frammento di programma
x = (int)(Math.random()*10);
estrae un numero a caso tra 0 e 10, 10 escluso (quindi tra 0 e 9).
Esercizio: Realizza un programma per la macchinetta del parcheggio: l'utente dovrà indicare il numero di ore che intende trattenersi. Se si vuole tenere la macchina al coperto c'è un'aggiunta di spesa di €5,00. Bisogna anche scegliere che mezzo parcheggiare: un camion costa (all'ora) €10,00, un camper cosa €5,00 ed un'automobile costa €3,50. Può altresì scegliere di parcheggiare per l'intera giornata: pagherà il costo di 5 ore. Mostrare il totale.
Esercizio: Realizza un programma per la gestione del Teenager's Bar: l'utente può scegliere un tipo di bevanda tra o il caffè (€0,80) o il succo d'arancia (€1,10) o il prosecco (€2,05). Può chiedere quante tazze/bicchieri ne vuole. Può altresì volere il servizio al tavolo che però gli costerà il 5% in più. Se sceglie di riconsegnare i vuoti al banco otterrà uno sconto di €0,50. Mostrare la spesa del cliente.
Esercizio: La palestra NewLook ha bisogno di un programma per il conteggio delle calorie bruciate. Per questo l'utente inserirà il numero di km percorsi. L'utente dovrà scegliere se quel percorso è stato fatto o a nuoto (km*21) o di corsa (km*12) o in bici (km*7) ottenendo le calorie bruciate. Se l'utente indossava bracciali per aumentare lo sforzo, le calorie realmente bruciate si ottengono moltiplicando il risultato ottenuto per 1,18. Analogo per le cavigliere moltiplicando per 1,35.
Esercizio: Le gite che entrano allo zoo di Mistoia pagano in base alla scuola degli studenti. Per coloro che non hanno la prenotazione si avrà un aggravio di €4,50 indipendentemente dai partecipanti. Se i ragazzi sono delle elementari ciascuno spende €6,00; se sono delle medie ciascuno spende €8,50 mentre delle superiori €9,50. Gli accompagnatori spendono la metà degli alunni. In fine, nei mesi invernali si ha uno sconto di €0,50 a ragazzo (no agli accompagnatori).