Oltre che utilizzare componenti già fatti o caricare immagini da disco adesso vorremmo disegnare qualcosa noi da programma... non è una esigenza così singolare!
In verità c'è un componente già fatto che ha lo stesso uso di una tela da disegno e, coincidenza, si chiama Canvas (per i più precisi il suo nome completo è javafx.scene.canvas.Canvas), questo componente lo possiamo piazzare in una parte della finestra a nostra scelta esattamente come facciamo con un Button o un TextField e ci consente di disegnarci su linee, cerchi, punti e via di seguito.
Vediamo direttamente un esempio:
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.layout.GridPane; import javafx.scene.paint.Color; import javafx.stage.Stage; public class HelloCanvas extends Application { @Override public void start(Stage primaryStage) { // creiamo un pannello specificando larghezza e altezza Canvas quadro = new Canvas(300, 260); // otteniamo l'oggetto che ci permette di disegnare GraphicsContext gc = quadro.getGraphicsContext2D(); gc.setFill(Color.YELLOW); gc.setLineWidth(1); gc.fillOval(50, 50, 200, 200); gc.setFill(Color.BLACK); gc.fillOval(100, 100, 20, 20); gc.fillOval(180, 100, 20, 20); gc.setStroke(Color.RED); gc.setLineWidth(8); gc.strokeLine(100, 200, 150, 220); gc.strokeLine(150, 220, 200, 200); GridPane root = new GridPane(); // inseriamo il nostro canvas nella finestra root.add(quadro, 0, 0); Scene scene = new Scene(root); primaryStage.setTitle("Hello Canvas!"); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
Come avrai notato non possiamo disegnare direttamente su un canvas ma ci serve ottenere un oggetto di tipo GraphicsContext che abbiamo chiamato gc.
Nell'esempio qui sopra disegnamo con diversi colori linee e ovali di spessori diversi, un oggetto GraphicsContext ha molte istruzioni per disegnare diversi tipi di forme geometriche come linee, rettangoli cerchi (sia pieni che vuoti) e molte altre.
Le coordinate nell'oggetto Canvas
Le coordinate funzionano come quello del piano cartesiano con alcune cose da tenere a mente:
- L'angolo in alto a sinistra del canvas è il punto (0,0)
- L'asse delle X cresce verso destra (come per il piano cartesiano usuale)
- L'asse delle Y cresce verso il basso (al contrario del piano cartesiano usuale)
Cerchio e linea
Nel disegno qui sotto (un Canvas di dimensioni 400x300) abbiamo 2 elementi:
- Una linea rossa che parte dal punto (0,100) e arriva al punto (400,50)
- Il cerchio verde in realtà è una ellisse, parte dal punto (50,0) (attenzione: non è il centro ma l'angolo in alto a sinistra del rettangolo che lo contiene) è larga 200 e alta 200

gc.setLineWidth(1); gc.setStroke(Color.RED); gc.strokeLine(0, 100, 400, 50); gc.setStroke(Color.GREEN); gc.strokeOval(50, 0, 200, 200);
Cerchio e quadrato
In questo altro disegno che usa un Canvas 200x200 abbiamo un quadrato rosso di lato 200 e un cerchio verde di diametro 200:
gc.setLineWidth(2); gc.setStroke(Color.RED); gc.strokeRect(0, 0, 200, 200); gc.setStroke(Color.GREEN); gc.strokeOval(0, 0, 200, 200);

Effetti speciali
Proviamo a modificare il programma precedente inserendo in start
un pulsante e l'usuale codice per gestire la sua pressione:
pulsante.setOnAction( e -> clickEffetto() );
Inseriamo poi prima della chiusura della classe il seguente frammento di codice:
public void clickEffetto(){ gc.applyEffect(new GaussianBlur(20)); }
Siccome l'oggetto gc viene usato sia in start che in clickEffetto dovremo anche spostare la sua dichiarazione (soltanto la dichiarazione!) al livello di classe (fuori da start).
Ora che il programma non ha più errori: che succede se si preme il pulsante?