Interfacce Grafiche Accessibili in Java

Tempo di lettura: 7 minuti

Continuiamo la serie di articoli su Maven e java. Oggi spiegheremo come creare un progetto sfruttando queste tecnologie, abbinate a open javafx per realizzare applicazioni con interfaccia grafica. 
Autore dell’articolo è “Francesco Calogero”, sviluppatore java ipovedente, che condividerà con noi la sua esperienza.


Al pari di come utilizziamo, in maniera accessibile, applicazioni per computer, quali ad esempio Eclipse, Word, Excel, con Java possiamo programmare noi stessi delle applicazioni con interfaccia utente anche accessibile, vedremo che non è per nulla difficile, grazie a JavaFx che si integra perfettamente con i più comuni strumenti di accessibilità dei nostri computer, come il contrasto elevato, i lettori di schermo o l’ingrandimento dello schermo, la nostra applicazione potrà essere utilizzata con o senza gli ausili.

Dalla versione 11 di Java il pacchetto java fx non è più integrato nel Jdk, tuttavia il framework continua ad essere aggiornato costantemente, ora si chiama Open javafx e grazie a Maven, seguendo le linee guida viste nel precedente articolo su Maven , possiamo includere nei nostri progetti la libreria OpenFx di cui abbiamo bisogno

Aggiungere Open JavaFx in Eclipse

Vediamo quindi passo passo come creare un progetto Maven da Eclipse includendo la libreria Open JavaFx:

  • Apriamo l’IDE Eclipse;
  • creiamo un nuovo progetto (premendo la combinazione “ctrl + n”);
  • nella schermata che appare, è presente un campo di ricerca. Premiamo “shift + tab” per raggiungerlo. Scriviamo al suo interno “maven”. Premiamo “tab”. Atterreremo così su un albero in cui dobbiamo scegliere “create a maven project”. Premiamo “invio” oppure “alt + n” per procedere;
  • Nella successiva schermata dobbiamo andare avanti premendo con “alt + n” il pulsante Next;
  • Nella maschera in cui ci viene richiesto di selezionare un archetype, se si tratta del primo progetto con cui vogliamo includere OpenJfx  dovremo prima aggiungere un nuovo archetype, quindi con “alt+ d” apriamo la finestra per l’aggiunta dell’archetype Qui scriviamo come “Archetype Group id” “org.openjfx” come “artifact id” scriviamo “javafx-archetype-simple” e come Archetype Versione,  “0.0.1” diamo invio e torniamo così nella maschera precedente; 
  • Con  “alt+ f”  andiamo nel campo filter e scriviamo “org.openjfx”, nell’elenco dei risultati di ricerca filtrati selezioniamo l’artifact id “javafx-archetype-simple”. Una volta selezionato, premiamo “invio” o “alt + n” per procedere;
  • Siamo nell’ultima schermata, dove inserire i parametri specifici del nostro progetto. Nel “groupId”, scriveremo la dichiarazione del package, ad esempio “it.corso.programmazione.java”. Definiamo poi un “artifact id”, un id che identifica in modo univoco il nostro progetto, scegliamo ad esempio il nome “helloworldFx”. Non modifichiamo il resto delle opzioni e premiamo “alt + f” che conclude la creazione del progetto.

A questo punto si chiuderà la schermata del wizard per la creazione di progetto e il focus su Eclipse tornerà al project explorer. Navigando l’albero del progetto all’interno della cartella “src/main/java”, Sotto la cartella java, dovremmo trovare il package “it.corso.programmazione.java.helloworldFx”.

In questo percorso è poi presente la classe “App.java”, tale classe contiene già un main pronto per l’uso che possiamo provare ad eseguire, dopo averlo aperto, con la consueta combinazione di tasti “ctrl+f11” dovrebbe aprirsi una finestra base di java fx se è così vuol dire che siamo pronti.

Applicazione Hello World 

Creiamo una nuova classe all’interno del nostro progetto helloworldFx che possiamo ad esempio chiamare “HelloWorldGui”. Ora incolliamo il seguente codice per realizzare una finestra con la scritta “Hello World!” 


import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class HelloWorldGui extends Application {
@Override
public void start(Stage stage) {
Label label = new Label("Hello World!");
Scene scene = new Scene(label);
stage.setScene(scene);
stage.setTitle("HelloWorld JavaFX");
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}

N.B :
Prestiamo attenzione alle classi che importiamo, devono avere sempre il suffisso javafx per funzionare correttamente.

La nostra classe HelloWorldGui, come si può notare, estende Application (del package javafx.application.Application), una classe astratta che richiede di implementare il metodo start , il punto di avvio della nostra applicazione, questo metodo prende in input un oggetto di tipo Stage (package javafx.stage.Stage) che possiamo considerare,in una metafora teatrale, come il palcoscenico della nostra interfaccia grafica. Lo Stage è appunto la finestra su cui rappresentare una scena della nostra applicazione, infatti all’interno del metodo start creiamo un oggetto di tipo Scene (package javafx.scene.Scene) a cui passiamo un oggetto Label ( package javafx.scene.control.Label) e poi un’etichetta che creiamo con la String “Hello World!”, quindi con stage.setScene(scene) diciamo allo Stage qual’è la Scene che deve far rappresentare, infine, dopo aver dato un titolo al nostro Stage con stage.setTitle(“HelloWorld JavaFX”), richiamiamo il metodo show() ,sempre dell’oggetto Stage, che farà visualizzare sullo schermo del nostro computer la finestra creata. Nel consueto metodo main dobbiamo solo richiamare il metodo launch(start) della classe Application che richiamerà il metodo start;

Da questa piccola applicazione possiamo quindi desumere che la nostra finestra viene popolata con una Scena che a sua volta è popolata da altri oggetti, quali Label,campi di testo, elenchi a tendina e via dicendo, questi oggetti sono detti nodi di controllo, infatti fanno parte del package javafx.scene.control, ora se volessimo aggiungere un altro controllo oltre alla Label dobbiamo prima comprendere come posizionare più Nodi di controllo in una Scene. 

Posizionamento dei Nodi di controllo in nodi di Layout

Come nelle più comuni interfacce grafiche per posizionare i nodi di controllo javafx usa dei nodi di tipo Layout, quindi invece di passare al costruttore di Scene un nodo di controllo Label, passeremo un nodo di Layout che al suo interno conterrà il nodo Label e anche gli altri nodi di controllo di cui abbiamo bisogno, proviamo quindi a vedere come aggiungere anche un campo di testo (javafx.scene.control.TextField), per cui , dopo aver creato la nostra Label con Label label = new Label(“Hello World!”); creiamo anche un oggetto TextField scrivendo TextField textField = new TextField(); ora abbiamo 2 oggetti di tipo controllo, uno denominato label e uno textField, ora creiamo il nostro Nodo di Layout, tra i tanti disponibili scegliamo il VBox, quindi lo creiamo e gli passiamo i nostri 2 nodi di controllo, il VBox (che possiamo tradurre in Vertical Box) è un controllo che posiziona i nodi uno sopra l’altro in verticale in base all’ordine con cui vengono passati, quindi se al costruttore di VBox passiamo prima label e poi il textField scrivendo VBox vbox = new VBox(label,textField) nella prima posizione in alto del VBox avremo la Label e sotto ad essa il textField, non ci rimane che passare al costruttore della Scene il vbox appena creato, scrivendo Scene scene = new Scene(vbox); il resto rimane invariato, di seguito il codice appena illustrato con dei commenti esplicativi : 


public void start(Stage stage) {
//creazione primo Node di controllo
Label label = new Label("Hello World!");
//creazione secondo Node di controllo
TextField textField = new TextField();
//creazione Nodo Contenitore per la gestione del Layout
VBox vbox = new VBox(label, textField);
//creazione oggetto Scene con nodo di Layout vbox
Scene scene = new Scene(vbox);
//abbinamento scena a stage
stage.setScene(scene);
//impostazione titolo allo Stage
stage.setTitle("HelloWorld JavaFX");
//lancio dello
Stage stage.show();
}

Aggiunta di un Button e di una TextArea.

il Button è il classico pulsante da cliccare, la TextArea è invece la tipica casella di testo che consente di scrivere del testo su più righe, a differenza del TextField visto poco prima che fornisce invece una sola riga su cui scrivere.

Per cui dopo la Label e il TextField, creiamo gli altri 2 oggetti appena descritti scrivendo : 

Button button = new Button("Clicca Qui!");
TextArea textArea = new TextArea();
//Aggiungo anche il button e la textArea al costruttore di VBox 
VBox vbox = new VBox(label, textField, button,textArea);

Controlli ed eventi

ora vogliamo fare in modo che al click sul button succeda qualcosa, per esempio ipotizziamo di voler trascrivere il testo dalla textfield alla nostra textArea.

Dobbiamo semplicemente richiamare sul nostro button il metodo setOnAction che è il metodo che ci consente di specificare il comportamento del button quando ci si clicca sopra.

Al metodo setOnAction dobbiamo obbligatoriamente passare un oggetto di tipo EventHandler, per tale scopo possiamo sfruttare la tecnica della classe anonima innestata, l’oggetto EventHandler richiederà l’implementazione del metodo handle : 

 


button.setOnAction(new EventHandler() {

		@Override
		public void handle(ActionEvent event) {

		  }
		 }
		);

quindi all’interno del metodo handle, appena creato, dobbiamo scrivere il codice che vogliamo venga eseguito al click sul button, nel nostro caso dovremo popolare la textArea, per cui il metodo start potrebbe essere scritto come segue : 


@Override
public void start(Stage stage) {
   //creazione primo Node di controllo
   Label label = new Label("Hello World!");
   //creazione secondo Node di controllo
   TextField textField = new TextField();
   //creazione del terzo Node di controllo
   Button button = new Button("Clicca Qui!");
   //creazione del quarto Node di controllo
   TextArea textArea = new TextArea();
 
  //Impostiamo l'evento di click sul Button
 button.setOnAction(new EventHandler<ActionEvent>() {
      @Override
      public void handle(ActionEvent event) {
        //metto il testo della textField in una String
        String testo = textField.getText();
        //aggiungo la String alla textArea e vado a capo
        textArea.appendText(testo+"\n");
        //cancello il contenuto della textField
        textField.clear();
    }
   });

Nel caso in cui il nostro programma dovesse gestire liste o elenchi, invece della TextArea potremmo utilizzare un controllo più adatto, come ad esempio il Node di controllo ListView che ci consente, come vedremo, di sfruttare le potenzialità del framework delle Collections di java, infatti la ListView ha un insieme di elementi su cui possiamo lavorare come se fossero delle List, ma prima vediamo qualche aspetto relativo all’accessibilità.

Impostazioni di Accessibilità

Nel metodo start sotto riportato con il metodo label.setLabelFor(textField) della Label facciamo in modo che quando il focus si trova sulla textField il lettore di schermo legga anche il testo della Label, inoltre ai controlli passiamo del testo da far leggere alla sintesi vocale con l’apposito metodo setAccessibleText che essendo un metodo di Node può essere richiamato su qualsiasi oggetto che estende Node, come Label, TextField, listView. Con il metodo requestFocus(), sempre di Node, facciamo in modo che una volta che abbiamo inserito del testo nella listView il Focus, e quindi il lettore di schermo si posizioni nella listView (vedere i commenti del seguente codice per maggiori dettagli o la documentazione)

public void start(Stage stage) {
	// creazione primo Node di controllo Label
	Label label = new Label("Benvenuto!");
	// creazione secondo Node di controllo
	TextField textField = new TextField("inserisci il tuo nome");
        // Mando un Testo da fare leggere alla sintesi vocale
	textField.setAccessibleText("Scrivi il Nome e premi Invio");
        //Collego la label alla textField
	label.setLabelFor(textField);
	// creazione del terzo Node di controllo
	Button button = new Button("Clicca Qui!");
        //Setto che il Tasto Enter crei un evento di click sul button
	button.setDefaultButton(true);
	// creazione del quarto Node di controllo
	ListView<String> list = new ListView<String>();
		
	// creazione Nodo di Contenuto che gestisce il Layout
	VBox vbox = new VBox(label, textField, button, list);
		
	// creazione oggetto Scene con nodo di Layout vbox
	Scene scene = new Scene(vbox);
	button.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
			// metto il testo della textField in una String
				String testo = textField.getText();
				// verifico che il testo non sia vuoto
				if (!testo.isEmpty()) {
//il metodo getItems mi restituisce la Collection degli elementi presenti // nella list a cui aggiungo la String testo con add
				list.getItems().add(testo);
				// cancello il contenuto della textField
				textField.clear();
				//setto il Focus sulla list View
				list.requestFocus();
				//selezione l'elemento aggiunto
				list.getSelectionModel().select(testo);
				//passo un Testo alla sintesi				    String txt = "Premi Tab per Tornare al TextField";
list.setAccessibleText("Aggiunto Nuovo Elemento nella Lista"); 					list.setAccessibleRoleDescription(AccessibleRole.LIST_VIEW +txt);
				}
			}

		});
		// abbinamento scena a stage
		stage.setScene(scene);
		// impostazione titolo allo Stage
		stage.setTitle("HelloWorld JavaFX");
		// lancio dello Stage
		stage.show();

	}

Volendo ragionare più ad oggetti invece di usare una classe anonima innestata, al metodo setOnAction di Button potremmo passare anche l’istanza di un oggetto vero e proprio che implementi EventHandler, scriveremmo così l’implementazione del metodo in una classe separata ma per accedere e settare i nostri controlli li dovremmo passare a questa classe.

Conclusioni

Dotare i nostri programmi di un’interfaccia grafica (Gui) è molto utile, anche solo per testare noi stesso il corretto funzionamento del nostro lavoro, oppure nel caso in cui volessimo far provare da subito il nostro software direttamente all’utente finale. Il pacchetto OpenFx che abbiamo introdotto in questo articolo ci consente di realizzare le nostre Gui, scrivendo poche righe di codice nel linguaggio java e sfruttando le potenzialità degli strumenti che già conosciamo, come Eclipse e Maven, Inoltre avremo da subito una Gui direttamente accessibile. Il Framework per l’interfacce è ricco di molte altre funzionalità,  una volta compresi i meccanismi di base, seguendo la documentazione e i tutorial reperibili nei link dei riferimenti sotto riportati, facilmente saremo in grado di ampliare le nostre applicazioni grafiche con tutto quello di cui abbiamo bisogno.

Riferimenti 

Pubblicato da

Francesco Calogero

Programmatore Java