back to top

Creare una calcolatrice in Java

Il linguaggio di programmazione Java offre senz’altro tra i suoi punti di forza semplicità e flessibilità. Sfrutteremo tali caratteristiche per realizzare, in un tempo davvero riddotto, una semplice calcolatrice dotata anche di un’interfaccia grafica.

Importazione delle librerie

Per quanto riguarda in particolare i componenti grafici della nostra calcolatrice in Java, utilizzeremo le librerie grafiche javax.swing, molto diffuse anche in contesti di maggiore completezza e complessità. L’utilizzo di tali librerie dovrà essere segnalato all’interno del nostro programma tramite l’istruzione:

import javax.swing;

Un’altra libreria di cui ci serviremo, per la gestione degli eventi come ad esempio la pressione dei tasti del PC, sarà la libreria java.awt, dunque sarà necessaria anche l’istruzione:

import java.awt.*;

La classe Calcolatrice: il cuore della nostra applicazione Java

Decidiamo di rappresentare la nostra calcolatrice come una classe di nome Calcolatrice. Le classi, strumento essenziale per la programmazione Java, sono costituite da dati e da metodi.

  • I dati, detti anche dati membro, rappresentano informazioni elementari (ad esempio il numero dei tasti).
  • I metodi rappresentano invece funzioni di elaborazione dei dati (ad esempio le azioni da compiere quando uno dei tasti viene premuto).

Ecco lo schema della classe Calcolatrice, che verrà commentato nel seguito punto per punto:

public class Calcolatrice
{  
    public static void main(String[] args){
        CalcolatriceFinestra calcolatriceFinestra = new CalcolatriceFinestra("Calcolatrice");
        calcolatriceFinestra.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        calcolatriceFinestra.setSize(300,300);
        calcolatriceFinestra.setVisible(true);        
    }
}

La classe Calcolatrice definisce soltanto un metodo particolare, detto metodo main. Tale metodo è infatti l’unico ad essere lanciato automaticamente all’esecuzione del programma. Con la prima riga del metodo main viene costruito un oggetto di tipo CalcolatriceFinestra.

Tale oggetto rappresenta la finestra applicativa che costituirà la nostra calcolatrice. Le ultime tre righe del codice sopra riportato utilizzano metodi propri della classe CalcolatriceFinestra. Tali metodi hanno come scopo, nell’ordine, di:

  • associare il clic del tasto sinistro del mouse sulla "X" nell’angolo a destra in alto presente nella finestra con la chiusura della stessa (metodo setDefaultCloseOperation)
  • definire le dimensioni della finestra (in questo caso 300×300 pixel, metodo setSize)
  • rendere visibile la finestra, che come impostazione predefinita risulterebbe invece nascosta e dunque non utilizzabile dall’utente (metodo setVisible)

Esaminiamo ora più nel dettaglio le caratteristiche della classe CalcolatriceFinestra.

La classe CalcolatriceFinestra

La classe CalcolatriceFinestra ci consente di creare una finestra al cui interno inseriremo i pulsanti e il display della calcolatrice. Per sviluppare classi di questo tipo, associate ad una finestra applicativa, Java mette a disposizione la classe JFrame, con molti metodi di utilità generale.

Sarà dunque conveniente fare in modo che la nostra classe CalcolatriceFrame abbia a disposizione i dati e i metodi propri di JFrame. Per far ciò, si dice che la classe CalcolatriceFinestra deriva da JFrame.

All’interno del codice, il processo di derivazione viene realizzato dalla parola chiave extends (class CalcolatriceFinestra extends JFrame).

A questo punto potranno essere aggiunti alla classe CalcolatriceFinestra altri elementi caratteristici. Al suo interno saranno presenti un’area di testo (il display) e un pannello con all’interno diversi pulsanti (i numeri da 0 a 9, +, -, *, /, oltre al punto per poter scrivere numeri non interi).

Ci serviremo per la costruzione del display della classe JTextField, presente all’interno delle librerie Java e che dunque non sarà necessario programmare autonomamente.

Per quanto riguarda il pannello invece varieremo la classe JPanel fornita da Java. Si utilizzerà dunque ancora una volta una classe derivata in questo caso proprio da JPanel, che chiameremo CalcolatricePannello.

La classe CalcolatriceFinestra avrà perciò due dati membro: uno di tipo JTextField e uno di tipo CalcolatricePannello, derivato da JPanel. Nel costruttore di CalcolatriceFinestra, dopo aver richiamato il costruttore di JFrame per mezzo della parola chiave super procediamo alla costruzione del display e del pannello per mezzo della parola chiave new.

I due elementi verranno poi aggiunti alla finestra con il metodo add. Le espressioni BorderLayout.NORTH e BorderLayout.CENTER indicano, rispettivamente, che il display verrà inserito nella parte alta della finestra e il pannello in quella centrale.

A questro punto curiamo meglio l’aspetto del display. In particolare grazie ai metodi:

  • setFont: per decidere il formato dei caratteri visualizzati sul display
  • setHorizontalAlignment: per stabilirne l’allineamento
  • setBackground: per scegliere il colore di sfondo
  • setEditable(false): per fare in modo che l’utente non possa scrivere all’interno del display se non servendosi degli appositi pulsanti

Ecco il codice della classe CalcolatriceFinestra:

public class CalcolatriceFinestra extends JFrame {
    private JTextField display;
    private CalcolatricePannello    bottoniera;
   
    public CalcolatriceFinestra(String titolo) {
        super(titolo);
        display = new JTextField();
        bottoniera = new CalcolatricePannello(this);
       
        add(display,BorderLayout.NORTH);
        add(bottoniera,BorderLayout.CENTER);
       
        display.setEditable(false);
        display.setFont(new Font("SansSerif",Font.ITALIC,22));
        display.setHorizontalAlignment(JTextField.RIGHT);
        display.setBackground(Color.LIGHT_GRAY);
       
    }

Restano a questo punto da sviluppare la classe CalcolatricePannello e le funzioni di calcolo per consentire effettivamente alla calcolatrice di eseguire operazioni aritmetiche.

La classe CalcolatricePannello

Il pannello contiene, come già detto, i diversi pulsanti necessari per il corretto funzionamento della calcolatrice. La classe opportuna da utiilizzare in Java per costruire pulsanti è JButton. La classe CalcolatricePannello avrà dunque come dato membro un array (un insieme), di oggetti di tipo JButton.

Ci servirà inoltre un altro dato per conservare il riferimento alla finestra in cui il pannello è inserito, perciò un dato di tipo CalcolatriceFinestra. Le funzioni di calcolo vengono eseguite dall’intera finestra (classe CalcolatriceFinestra), ma il clic viene effettuato sui pulsanti, presenti invece all’interno della classe CalcolatricePannello. Ecco perchè è necessario un meccanismo di collegamento tra le due classi.

Definiremo a questo punto il layout (schema grafico) del pannello per mezzo del metodo setLayout e del modello GridLayout (una semplice griglia 4×4).

A questo punto faremo in modo che ciascun bottone venga creato (tramite la parola chiave new), abbia un determinato colore di sfondo (metodo setBackground) e sia in grado di riconoscere il clic del mouse, che indica la pressione di quello specifico tasto sulla calcolatrice.

Per quest’ultimo scopo Java mette a disposizione l’interfaccia ActionListener: utilizzeremo ancora una volta una classe derivata, o meglio, in questo caso, un’interfaccia derivata, che chiameremo BottoniListener.

All’interno di BottoniListener ridefiniremo il metodo ActionPerformed, che viene eseguito automaticamente ogniqualvolta si verifica un evento, come ad esempio il clic del mouse.

Identificheremo all’interno di tale metodo, tramite la funzione predefinita getSource, l’evento che si è verificato ovvero, in questo caso, quale tasto è stato premuto.

A questo punto, valutando se il tasto premuto corrisponde ad una cifra, al punto o ad un operatore (+,-,*,/) si richiamerà l’opportuna funzione di calcolo all’interno della classe CalcolatriceFinestra. Ecco il codice della classe CalcolatricePannello:

public class CalcolatricePannello extends JPanel {
   
   private JButton[] bottoni = {
            new JButton("1"), new JButton("2"), new JButton("3"), new JButton("+"),
            new JButton("4"), new JButton("5"), new JButton("6"), new JButton("-"),
            new JButton("7"), new JButton("8"), new JButton("9"), new JButton("*"),
            new JButton("0"), new JButton("."), new JButton("="), new JButton("/")
    };
   
    private CalcolatriceFinestra mainFrame;
   
    public CalcolatricePannello(CalcolatriceFinestra calcFin) {
        mainFrame = calcFin;
        setLayout(new GridLayout(4,4));
        BottoniListener listenerBottoni = new BottoniListener();
        for (int i = 0; i < bottoni.length; ++i) {
            bottoni[i].setBackground(Color.ORANGE);
            add(bottoni[i]);
            bottoni[i].addActionListener(listenerBottoni);
        }
    }
   
    private class BottoniListener implements ActionListener {
        public void actionPerformed(ActionEvent ev) {
            JButton pressed = (JButton)ev.getSource();
            char c = pressed.getText().charAt(0);
            if ((c >= '0') && (c <= '9')) {
                mainFrame.inseritaCifra(c);
            } else if (c == '.') {
                mainFrame.inseritoPunto();
            } else {
                mainFrame.inseritoOperatore(c);  
            }
        }
    }
}

Concludiamo esaminando proprio le funzioni di calcolo inserite nella classe CalcolatriceFinestra.

Funzioni di calcolo

Per programmare le funzioni di calcolo ci serviremo di tre variabili che verranno memorizzate, come già accennato, nella classe CalcolatriceFinestra. Si tratta di:

  • una variabile di tipo double (numero con virgola) per tenere traccia del numero che si sta attualmente trattando, il nome della variabile sarà operandoCorrente
  • una variabile di tipo char (carattere) per memorizzare l’ultimo operatore digitato (+,-,*, / o =), di nome operatoreCorrente
  • una variabile di tipo boolean (vero/falso) per poter verificare se il display è stato o meno resettato, di nome resetDisplay

Ecco dunque la dichiarazione delle tre variabili:

private double  operandoCorrente  = 0.0;
private char    operatoreCorrente = '?';
private boolean resetDisplay = true;

Si realizzano poi quattro funzioni distinte, come metodi di CalcolatriceFinestra:

  • per gestire l’inserimento di una nuova cifra (inseritaCifra)
  • per l’inserimento del punto per i numeri con virgola (inseritoPunto)
  • per controllare l’inserimento di un operatore (inseritoOperatore)
  • per il vero e proprio calcolo del risultato (calcolaRisultato)

La funzione inseritaCifra verifica inizialmente se il display è in stato di reset. In tal caso imposta il testo del display ad un semplice spazio vuoto. Dopo tale controllo il testo visualizzato sul display è lo stesso di prima dell’esecuzione della funzione (recuperato tramite il metodo getText) più il carattere appena inserito. Ecco il codice della funzione:

public void inseritaCifra( char c ) {
        if (resetDisplay) {
            display.setText("");
            resetDisplay = false;
        }
        display.setText(display.getText() + c);
    }

Il metodo inseritoPunto è del tutto analogo a inseritaCifra, con l’unica differenza che il carattere da aggiungere al display è fissato ed é ".", come si può verificare:

public void inseritoPunto() {
        if (resetDisplay) {
            display.setText("");
            resetDisplay = false;
        }
        display.setText(display.getText() + ".");
    }

Il metodo inseritoOperatore distingue al proprio interno diversi casi. In caso l’operatore corrente sia "=" è necessario calcolare un risultato. Ad esempio alla sequenza "2+3=" è necessario calcolare e visualizzare il risultato "5".

Il dato presente al momento della digitazione di "=" sul display (cioè il secondo numero oggetto dell’operazione) viene dunque convertito a numero con virgola (tramite la funzione parseDouble) e memorizzato in una nuova variabile operando.

A questo punto passiamo l’operatore e i due operandi (ovvero i due numeri) alla funzione calcolaRisultato, che verrà trattata in seguito. Memorizziamo il valore di ritorno della funzione in una nuova variabile risultato e visualizziamola sul display, che passa in stato di reset.

La calcolatrice ha infatti eseguito un’operazione completa e si trova quindi in uno stato equivalente a quello di partenza.

In caso l’operatore corrente sia diverso da "=" e non si abbia un altro operatore già in memoria ci limiteremo a memorizzare il numero presente sul display (in questo caso il primo operando) nella variabile operandoCorrente.

Se invece è già presente un operatore in memoria, è necessario svolgere un calcolo intermedio. Una sequenza da parte dell’utente è infatti di tipo operando, operatore, operando e così via (ad esempio "2+3*4"…).

All’inserimento del secondo operatore quindi, sono già a disposizione due operandi e un operatore, sufficienti per il calcolo di un risultato parziale. Come nel caso in cui l’operatore sia "=" (trattato in precedenza) il contenuto del display è convertito e salvato in una variabile operando.

Ancora una volta il risultato viene calcolato dalla funzione calcolaRisultato il cui valore di ritorno viene però memorizzato non nella variabile risultato, ma nella variabile operandoCorrente, proprio perchè non è soltanto un risultato parziale, ma il primo numero per l’operazione successiva.

Dopo tali operazioni, in ogni caso, il valore dell’operatore inserito viene salvato all’interno della variabile operatoreCorrente. Ecco il codice della funzione inseritoOperatore:

public void inseritoOperatore( char c ) {
        if (c == '=') {
            if (operatoreCorrente != '?') {
                double operando = Double.parseDouble(display.getText());
                double risultato =
                    calcolaRisultato(operandoCorrente, operando, operatoreCorrente);
                display.setText(String.valueOf(risultato));
                operatoreCorrente = '?';
                resetDisplay = true;
            }
        } else {
            // Gestire l'operatore
            if (operatoreCorrente == '?') {
                operandoCorrente = Double.parseDouble(display.getText());
            } else {
                double operando = Double.parseDouble(display.getText());
                operandoCorrente =
                    calcolaRisultato(operandoCorrente, operando, operatoreCorrente);
                display.setText(String.valueOf(operandoCorrente));

            }
            operatoreCorrente = c;
            resetDisplay = true;
        }
    }

Per mezzo di un semplice costrutto switch, del tutto equivalente ad una serie di istruzioni if (cioè di tipo se…allora…) è possibile realizzare anche la funzione calcolaRisultato:

private double calcolaRisultato(double op1, double op2, char oper) {
        switch (oper) {
        case '+' : return (op1 + op2);
        case '-' : return (op1 - op2);
        case '*' : return (op1 * op2);
        case '/' : return (op1 / op2);
        default : return 0.0;
        }
    }

A questo punto la calcolatrice, sia pure molto semplice ed essenziale, è completa e può essere visualizzata e utilizzata.

Conclusioni

In questo articolo abbiamo visto come programmare una completa calcolatrice in Java: si tratta di un esercizio utile per prendere familiarità con la gestione delle operazioni matematiche con Java che rappresentano, senza dubbio, uno degli aspetti più importanti nell’ambito della programmazione.

Altri contenuti interessanti

Pubblicità

Leggi anche...

Java: cos’è e a cosa serve l’operatore modulo (%)

In Java, l'operatore modulo è rappresentato dal simbolo "%"...

Arrotondare un numero con Java

Quando si lavora con i numeri all'interno di un...

Java: cos’è l’errore NullPointerException e come risolverlo

RuntimeException è una superclasse di Java che ricomprende tutte...

Stringhe in Java

La gestione delle stringhe assume un ruolo fondamentale in...

Leggere un file di testo in java

In java ci sono diverse modalità per leggere dati...

Il costrutto foreach in java

Il foreach è un particolare costrutto (disponibile a partire...
Pubblicità