GRAFICA ED EVENTI SWING, AWT e JavaFX argomenti • JavaFX: architettura e gerarchia • Componenti principali: Stage, Scene, contenuti • Gestione degli eventi STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE Java Package Grafici I package grafici che comprende tutt’ora il JDK sono a grandi linee i seguenti: • Package java.awt (Abstract Window Toolkit): – il primo package grafico (Java 1.0) – indipendente dalla piattaforma... o quasi! • Package javax.swing: – il secondo package grafico (Java 2; versione preliminare da Java 1.2) – scritto esso stesso in Java, realmente indipendente dalla piattaforma • Package javafx: – L’ultimo package grafico (Java 7) – Scritto interamente in Java, alcune applicazioni swing possono girare sotto JavaFX Scendiamo più in dettaglio nel package JavaFX. STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE Java Package: JavaFX • Il Package di Swing è potente, flessibile e IMMENSO. • Il numero dei package disponibili è alto, molti programmi usano un piccolo subset di package disponibili. • Programmazione “event-driven”: – non più algoritmi stile input/elaborazione/output... – ... ma reazione agli eventi che l’utente, in modo interattivo, genera sui componenti grafici STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: COMPONENTI PRINCIPALI • La main class in una applicazione JavaFX eredita dalla classe javafx.application.Application . Il metodo start() è il punto d’ingresso delle applicazione JavaFX. • In JavaFX, le applicazioni definiscono un container per l’intefaccia utente mediane l’uso di un stage e una scene. • JavaFX Stage è il contenitore principale • JavaFX Scene è quello che mostra il contenuto dell’interfaccia • In JavaFX, il contenuto della scena è rappresentato come una gerarchia di nodi. STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: esempio1 import import import import import import import javafx.application.Application; javafx.event.ActionEvent; javafx.event.EventHandler; javafx.scene.Scene; javafx.scene.control.Button; javafx.scene.layout.StackPane; javafx.stage.Stage; public class EmptyWindow extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Hello World!"); StackPane root = new StackPane(); primaryStage.setScene(new Scene(root, 300, 250)); primaryStage.show(); } } STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: esempio1 • Il risultato dell’esecuzione: STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: esempio2 • Nell’esempio precedente abbiamo creato una finestra completamente vuota • Vediamo un esempio di come si possono inserire componenti nella nostra applicazione. STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: esempio2 public class HelloWorld extends Application { @Override public void start(Stage primaryStage) { Button btn = new Button(); btn.setText("Say 'Hello World'"); btn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { System.out.println("Hello World!"); } }); StackPane root = new StackPane(); root.getChildren().add(btn); Scene scene = new Scene(root, 300, 250); primaryStage.setTitle("Hello World!"); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: Layout • Nell’esempio precedente usiamo uno StackPane. Il problema è che questo layout posiziona tutto in centro e quindi non è il migliore da usare. STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: disegnare forme generiche • Prima di tutto bisogna settare come radice un oggetto di tipo Group • Va in seguito creato un Canvas, una tela, dove verranno disegnate le figure Group root = new Group(); Canvas canvas = new Canvas(300, 250); • Dall’oggetto Canvas si recupera il graphic context dove fisicamente si disegnerà GraphicsContext gc = canvas.getGraphicsContext2D(); • Si disegnano le figure e infine si aggiunge il canvas al nodo radice. STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: soluzione public void start(Stage primaryStage) { // settaggio finestra primaryStage.setTitle("Finestra con forme"); // creazione root e canvas Group root = new Group(); Canvas canvas = new Canvas(300, 250); // Recupero GraphicsContext GraphicsContext gc = canvas.getGraphicsContext2D(); // disegno le forme drawShapes(gc); // aggiungo il canvas a root root.getChildren().add(canvas); primaryStage.setScene(new Scene(root)); primaryStage.show(); } STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: soluzione private void drawShapes(GraphicsContext gc) { gc.setFill(Color.GREEN); gc.setStroke(Color.BLUE); gc.setLineWidth(5); gc.strokeLine(40, 10, 10, 40); gc.fillOval(10, 60, 30, 30); gc.strokeOval(60, 60, 30, 30); gc.fillRoundRect(110, 60, 30, 30, 10, 10); gc.strokeRoundRect(160, 60, 30, 30, 10, 10); gc.fillArc(10, 110, 30, 30, 45, 240, ArcType.OPEN); gc.fillArc(60, 110, 30, 30, 45, 240, ArcType.CHORD); ... STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: soluzione ... gc.fillArc(110, 110, 30, 30, 45, 240, ArcType.ROUND); gc.strokeArc(10, 160, 30, 30, 45, 240, ArcType.OPEN); gc.strokeArc(60, 160, 30, 30, 45, 240, ArcType.CHORD); gc.strokeArc(110, 160, 30, 30, 45, 240, ArcType.ROUND); gc.fillPolygon(new double[]{10, 40, 10, 40}, new double[]{210, 210, 240, 240}, 4); gc.strokePolygon(new double[]{60, 90, 60, 90}, new double[]{210, 210, 240, 240}, 4); gc.strokePolyline(new double[]{110, 140, 110, 140}, new double[]{210, 210, 240, 240}, 4); } • NOTA: fill identifica figure piene, stroke il bordo STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: disegnare forme generiche • Il risultato dell’esecuzione è il seguente: STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: Eventi • Finora si sono utilizzate alcune delle funzionalità di JavaFX, ma l’interazione con l’utente non è stata presa in considerazione. • Ogni applicazione deve poter interagire con l’utente, e per fare questo deve essere reattiva su alcuni componenti, che quindi devono essere in grado di determinare il proprio stato e lanciare opportuni segnali quando questo viene modificato dall’utente. • Ogni componente grafico, quando si opera su di esso, genera un evento che descrive cosa è accaduto. • Tipicamente, ogni componente può generare molti tipi diversi di eventi, in relazione a ciò che sta accadendo: – un bottone può generare l’evento “azione” che significa che è stato premuto; – una casella di opzione può generare l’evento “modificato” per indicare che la casella è stata selezionata / deselezionata. STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: Eventi • Un modo semplice per definire un metodo per gestire eventi differenti è quello di definire una classe che implementa l’interfaccia EventHandler. • La classe creata dovrà implementare il metodo handle(Event e) preposto alla gestione dell’evento stesso. In questo metodo verrà inserita la logica che gestirà l’evento scatenato. STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: Eventi - un esempio Per provare a gestire qualche evento, proviamo a scrivere un programma che implementi una semplice calcolatrice. Architettura: • un pannello con un campo di testo e sei pulsanti • un unico EventHandler per tutti i pulsanti (è il vero calcolatore) Gestione degli eventi: Ogni volta che si preme un pulsante: • si recupera il nome del pulsante • si legge il valore nel campo di testo • si svolge l'operazione precedente STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: Eventi – esempio architettura • • Per semplicità nella gestione degli definiamo i bottoni e il campo di testo come attributi della classe. La classe che implementerà EventHandler sarà interna alla classe principale del nostro programma. Infine, nel metodo start() cominciamo a creare i bottoni e il campo di testo public class MyCalculator extends Application { TextField txt; Button btnadd, btnsub, btndiv, btnmul, btnclear, btneq; @Override public void start(Stage primaryStage) { txt = new TextField(); btnadd = new Button("+"); btnsub = new Button("-"); btnmul = new Button("x"); btndiv = new Button("/"); btneq = new Button("="); btnclear = new Button("Clear"); STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: Eventi – esempio architettura • Il posizionamento degli elementi verrà effettuato usando un GridPane. Settiamone le caratteristiche e aggiungiamo i componenti. GridPane root = new GridPane(); root.setAlignment(Pos.CENTER); // gap fra i componenti di ogni riga/colonna root.setHgap(10); root.setVgap(10); root.add(txt, 0, 0, 4, 1); root.add(btnadd, 0, 1); root.add(btnsub, 1, 1); root.add(btnmul, 2, 1); root.add(btndiv, 3, 1); // definisco che il bottone srà contenuto in più colonne (4) root.add(btneq, 0, 2, 4, 1); root.add(btnclear, 0, 3, 4, 1); STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: Eventi – esempio architettura • Collego il gestore degli eventi ai bottoni e setto i parametri della finestra. MyEventHandler eh = new MyEventHandler(0); btnadd.setOnAction(eh); btnsub.setOnAction(eh); btnmul.setOnAction(eh); btndiv.setOnAction(eh); btneq.setOnAction(eh); btnclear.setOnAction(eh); Scene scene = new Scene(root, 340, 160); primaryStage.setTitle("Mini Calcolatrice"); primaryStage.setScene(scene); primaryStage.show(); } // definisco il main public static void main(String[] args) { launch(args); } STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: Eventi – esempio architettura • Infine definisco la classe gestore degli eventi class MyEventHandler implements EventHandler { private double result; private String precOp; // costruttore public MyEventHandler(double result) { this.result = result; precOp = "nop"; } STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: Eventi – esempio architettura @Override public void handle(Event e) { double num; String operazione; num = Double.parseDouble(txt.getText()); if (e.getSource() == btnclear) { txt.setText(""); txt.requestFocus(); result = 0; precOp = "nop"; } else { ... STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX: Eventi – esempio architettura if (e.getSource() == btnadd) operazione = "+"; } else if (e.getSource() == operazione = "-"; } else if (e.getSource() == operazione = "*"; } else if (e.getSource() == operazione = "/"; } else { operazione = "nop"; } { btnsub) { btnmul) { btndiv) { STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX : Eventi – esempio architettura if (precOp.equals("+")) { result += num; } else if (precOp.equals("-")) { result -= num; } else if (precOp.equals("*")) { result *= num; } else if (precOp.equals("/")) { result /= num; } else if (precOp.equals("nop")) { result = num; } txt.setText("" + result); precOp = operazione; txt.requestFocus(); } } } } STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE JavaFX : Eventi - risultato • Il risultato dovrebbe essere il seguente: • Abbiamo utilizzato un unico gestore di evento per prelevare e gestire tutti gli eventi dei pulsanti che abbiamo creato. • Ci sono pattern di programmazione migliori di questo. STRUMENTI JAVA PER LO SVILUPPO DI INTERFACCE UTENTE E SERVIZI DI RETE E LORO APPLICAZIONE