gui

passo per passo il primo programma funzionante con interfaccia grafica

I nostri programmi saranno scritti usando Java e la sua interfaccia grafica JavaFX, per la creazione del nostro primo progetto in vai sul menu File/New/Project... nella finestra che si apre apri il gruppo Java e seleziona Java Project e poi premi Next > vai sul menu File/New Project... nella finestra che si apre scegliere come categoria Samples/OpenJFX e poi in Projects esempio JavaFX. Ora indica il nome del progetto (per esempio ciaoMondo) e termina con Finish. se viene chiesto di creare il file "module-info.java" rispondere di no. Il progetto nuovo comparirà sulla sinistra.

Nello svolgere le prossime operazione fai attenzione al Maiuscolo/minuscolo nei nomi degli elementi: apri le cartelle del progetto, diventerà visibile una cartella src Source Packages, fai click con il destro e poi click sul menu contestuale New/class, chiamala CiaoMondo (nel campo Name) e scrivi ciaomondo nel campo Package. A questo punto fai doppio click sulla classe appena creata per aprirla.

Il file "CiaoMondo", conterrà qualche linea di codice che va cancellata e sostituita con il programma qui sotto:

Il file "CiaoMondo", conterrà il testo qui sotto.

package ciaomondo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

/**
 * @author aspix
 */
public class CiaoMondo extends Application {
   
   Button btn = new Button();
   
   @Override
   public void start(Stage primaryStage) {
      btn.setText("Saluta!");
      btn.setOnAction(e -> esegui());
        
      StackPane root = new StackPane();
      root.getChildren().add(btn);
        
      Scene scene = new Scene(root, 300, 250);
        
      primaryStage.setTitle("Hello World!");
      primaryStage.setScene(scene);
      primaryStage.show();
   }
   
   private void esegui(){
      btn.setText("Ciao Mondo!");
   }

   /**
    * @param args the command line arguments
    */
   public static void main(String[] args) {
      launch(args);
   }
}

Non tutto ciò che vi è scritto viene interpretato dal computer: noterai alcune parti sono racchiuse dal simboli /* e */. Tali delimitatori indicano i commenti, cioè cose che il programmatore inserisce a scopo chiarificatore affinché altri (o lui stesso) possano meglio capire cosa fa quella parte di programma. In questi commenti spesso si inserisce un asterisco ad ogni inizio riga ma solo per motivi estetici e di leggibilità. Tutti i commenti appariranno nell'editor come un testo grigio e verranno scartati in fase di compilazione.

Un modo alternativo per inserire il commento è scrivere //commento. Quando viene incontrata la doppia barra, tutto il resto della riga è un commento, quindi si possono anche qui inserire considerazioni. Dato che è fino al termine della riga, non serve una chiusura.

La prima riga non dice al programma cosa fare ma piuttosto serve ad inserire questo file in una gerarchia. Noi abbiamo sbrigativamente scritto il nome ciaomondo ma non è questa la pratica: i programmi sono solitamente fatti da tanti file e usualmente almeno in parte non scritti da noi, per questo avere tutto mantenuto in maniera ordinata è di aiuto allo sviluppo. La strategia standard per gestire i pacchetti è piuttosto semplice: ogni classe (per adesso possiamo considerare che un file sia la stessa cosa) appartiene ad un pacchetto il cui nome possiamo deciderlo noi (al solito scritto tutto in minuscolo), questo pacchetto può essere a sua volta contenuto in altri pacchetti e così via. Ogni pacchetto in pratica è una cartella e la struttura inizia con il nome del dominio (che vengono registrati pubblicamente) scritto al rovescio... sembra complicato?

Il dominio della mia organizzazione è aspix.it e sto scrivendo il programma per una chat come chiamerò il pacchetto?

mio pacchettonon possono esserci spazi chat il nome sarebbe sensato ma non contiene il nome del dominio chat.it.aspix il nome del dominio non va messo in fondo it.aspix.chatesatto! prima il dominio di primo livello e poi di seguito le altre parti

Nella pratica i pacchetti sono delle cartelle quindi la classe Prova che sta nel pacchetto com.azienda.esperimenti sarà un file che si chiama Prova che sta nella cartella esperimenti che a sua volta sta nella cartella azienda contenuta nella cartella com.

Il gruppo successivo indica tutte le funzionalità di cui ha bisogno questa parte di programma per funzionare (detto nei termini di java: gli altri oggetti che useremo); queste vengono importate (import) per poter essere poi usate nel programma. La riga contenente la parola chiave class indica – per ora – la nostra finestra (il programma in esecuzione appare all'utente come una finestra). Osserva che a fine riga c'è una { ed in fondo al file c'è la rispettiva }. Queste parentesi rappresentano rispettivamente l'inizio e la fine di tutto ciò che farà la finestra, contengono cioè le istruzioni del nostro programma.

Una istruzione è una parte elementare del programma che viene eseguita dalla macchina e determina l'avanzamento del processo in memoria.

Procediamo con la lettura, la riga contenente start indica la prima funzionalità del nostro programma, quella cioè che viene avviata nel momento in cui deve essere disegnata la finestra (da cui, appunto, start). Nota che anch'essa ha la { a fine riga e si conclude con la corrispettiva }. Le graffe delimitano l'insieme di istruzioni che deve essere eseguito. Quando scriveremo nostre funzionalità useremo le graffe per raccogliere tutte le istruzioni atte a raggiungere il risultato previsto.

Button btn = new Button();

Si tratta di una dichiarazione di variabile. Le dichiarazioni di variabile hanno la sintassi:

tipo nomeVariabile;
Una variabile è una zona di memoria identificata da un nome che contiene una sola informazione di un determinato tipo detta valore, questa informazione può variare nel tempo.

in questo caso il tipo è Button ed il nome della variabile è btn. Alcune variabili sono ti un tipo semplice come un intero, un numero con la virgola, un carattere ecc.; altre variabili sono invece più complesse come in questo caso, in tal caso bisogna aggiungere alla dichiarazione = new tipo(). Il perché lo vedremo tra un po' di tempo. Ogni componente di una finestra è un tipo non semplice, quindi per ciascuno di esso dovremo usare questa specifica sintassi. Essendo il punsante un tipo non semplice, tale parte va aggiunta. Se avessi dovuto dichiarare invece un oggetto di tipo testo avresti dovuto scrivere

Label testo = new Label();

Il pulsante ancora non ha un testo al suo interno da mostrare all'utente. Questo si imposta con la riga successiva: btn.setText("Say 'Hello World'"). Osserva la strana sintassi d'inizio riga: btn. che in generale è nomeVariabile.: tale notazione sta a significare “sto parlando dell'oggetto btn”; cosa si vuol fare con l'oggetto in questione è specificato subito dopo ed in questo caso si tratta di impostare il testo, appunto setText(“Testo da mostrare”).

Quale istruzione si usa per utilizzare nel nostro programma degli elementi (oggetti) scritti da altri?

class la usiamo per definire qualcosa di nuovo noi import StackPane questo è il nome di uno specifico oggetto Copyright non compare nel nostro programma

Quali parentesi si usano per raggruppare delle parti di codice?

tonde () quadre [] graffe {} angolari <>

Salta qualche riga sulle quali si torna tra pochissimo ed arriva a:

StackPane root = new StackPane()

si vede subito che si tratta di una dichiarazione di una variabile di tipo StackPane chiamata root. Tutti gli oggetti grafici che utilizzi nella finestra (pulsanti, caselle di testo, elenchi, ...) devono essere disposti in quello che possiamo considerare il pannello di una bacheca mentre i nostri oggetti sono il contenuto di tale bacheca. Lo StackPane impila (mette uno sopra l'altro come la pila di piatti) gli oggetti da inserire nel pannello. Se abbiamo ad esempio 3 oggetti, questi verranno sovrapposti gli uni sugli altri. Questo non è l'unico modo per organizzare gli elementi dell'interfaccia grafica.

Arrivi a

root.getChildren().add(btn);

parli di root ed utilizzi la funzionalità getChildren(). ma non finisce qui perché di quest'ultima, a sua volta, vogliamo usare la funzionalità add, cioè aggiungere (un elemento); l'elemento da aggiungere è indicato nelle parentesi, in questo caso il pulsante btn. Osserva che aggiungendo in questo modo oggetti non puoi specificare in quale posizione metterli.

Uno degli oggetti che si usano come contenitore di altri elementi dell'interfaccia grafica si chiama:

Label questa è una singola etichetta (testo non modificabile dall'utente) Button questo è il pulsante StackPane Scene questa è l'area interna della finestra

La riga successiva contiene ancora una dichiarazione:

Scene scene = new Scene(root, 300, 250);

la scena indica l'area contenuta nella finestra vera e propria. Tale dichiarazione è leggermente diversa da quanto affermato (per semplicità) fino ad ora: le parentesi tonde in questo caso hanno un contenuto, questo perché in questo caso per costruire un nuovo oggetto Scene servono delle informazioni in più. Il primo argomento – root – sta ad indicare come si chiama il pannello da inserire in quest'area mentre il secondo ed il terzo – 300, 250 – ne indicano le misura (larghezza, altezza), quindi indicano la misura della finestra a meno dei bordi e della barra del titolo.

cosa fa il seguente frammento di programma?

/* StackPane root = new StackPane() */
crea un nuovo StackPane potrebbe sembrare... ma è contenuta in /* */ avvia il programma per avviare un programma bisogna usare altri strumenti niente giusto! è un commento

Andando avanti vedi l'uso della funzionalità .setTitle(“il titolo”) per l'oggetto primaryStage. Tale oggetto, che è la finestra vera e propria, non deve essere dichiarato in quanto viene già fornito al tuo programma. Tornando alla funzionalità, questa imposta il testo da visualizzare sulla barra del titolo della tua applicazione. La linea che segue abbina la finestra con la sua scena, cioè la sua area tramite primaryStage.setScene(scene).

Non resta che visualizzare, mostrare (show) la finestra e tutto il suo contenuto. Lo fai tramite l'ultima riga:

primaryStage.show();

Da osservare che questa è l'ultima istruzione della funzionalità start. Ciò significa – tra l'altro – che tutte le variabile qui dichiarate appena fatta la show() finiranno di essere accessibili, in quanto la } fa scomparire tutti i nomi. Altre funzionalità non potranno quindi farne uso. Si termina con la funzionalità .setOnAction di btn indicante le azioni da intreprendere nel caso l'utente interagisca con l'oggetto in questione (ancora, il pulsante). In questo caso il programma farà una sola cosa: scriverà sul pulsante il messaggio Hello world!