Oggetti grafici

Quarta lezione del tutorial sun sulla creazione di applicazioni GUI con javaFX, qui si riprende il discorso fatto nella prima lezione, mostrando come combinare gli oggetti grafici forniti da javaFX per crearne di nuovi da usare nelle nostre applicazioni.

Iniziamo vedendo un esempio per il common profile, poi lo estenderemo per il desktop profile che permette di applicare effetti che lo rendono ancor più attraente.

Common Profile

Diciamo che vogliamo creare un lettore audio. L'esempio che trattiamo qui si limita a mostrare come creare il bottone "play", una freccia che, pigiata, lo farà partire.

Per crearlo, combineremo oggetti e effetti resi disponibili da javaFX e che abbiamo introdotto nella prima lezione di questo tutorial.

Prima di costruire un nuova componente, é una buona idea dare un'occhiata in giro per vedere cosa c'é già disponibile in giro. Con javaFX sono messi a disposizione una serie di utili componenti nel package standard javafx.scene.control.

In ogni caso, il nostro primo passo é quello di creare un nuovo file, chiamiamolo play.fx, ad esempio.

La finestra della applicazione

Ormai la cosa ci dovrebbe riuscire naturale, importiamo la classe Stage e ne dichiariamo una istanza, assegnando al su attributo title quello sarà il titolo la finestra principale della nostra applicazione.

import javafx.stage.Stage;

Stage {
title: "Play Button"
}

La scena

All'interno dello stage prepariamo la scena in cui verrà mostrato il nostro bottone. Aggiungiamo perciò un import per le classi Scene, Color e Group, dichiariamo un oggetto Scene all'interno del nostro Stage, definiamo il colore di sfondo che vogliamo usare e specifichiamo gli oggetti contenuti nella nostra scena inizializzando la sua proprietà content con un instanza della classe Group. Al momento non ci sono oggetti, perciò definiamo come content del nostro gruppo solo un'array vuoto:

...
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.Group;

Stage {
...

scene: Scene {
width: 250, height: 350
fill: Color.WHITE
content: Group {
content: []
} //Group
} //Scene
}

Nota che la definizione delle dimensione della scena non sarebbe richiesta se la nostra applicazione corresse solo su un mobile, dato che verrebbe assunto per default che usasse tutto lo spazio a disposizione. Nel nostro caso vogliamo che sia utilizzabile anche per desktop.

Lo sfondo del bottone

Vogliamo che il nostro bottone abbia un sfondo un poco elaborato. Lavoriamo con rettangoli, perciò aggiungiamo l'import per la classe Rectangle. Vogliamo usare sfumature nei colori e per far ciò importiamo le classi LinearGradient e Stop.
L'idea é quella di avere tre rettangoli sovrapposti, racchiusi da una cornice ad angoli smussati, in varie tonalità di blu sfumate.

La struttura del nostro script verrà perciò estesa in questo modo:

...
import javafx.scene.shape.Rectangle;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;

Stage {
...

scene: Scene {
...
content: Group {
content: [
Rectangle {
...
}

Rectangle {
...
}

Rectangle {
...
}

Rectangle {
...
}
]
} //Group
} //Scene

Il primo rettangolo descriverà l'area in alto:

Rectangle {
x: 48, y: 46, width: 150, height: 59
stroke: Color.GREEN
fill: LinearGradient {
startX: 0.0, startY: 1.0, endX: 0.0, endY: 0.0,
proportional: true
stops: [
Stop { offset: 0.0, color: Color.web("#aaeeff") },
Stop { offset: 1.0, color: Color.web("#66aacc") }
]
} // fill
}

Si tratta di un rettangolo contornato da una sottile riga verde, sfumato usando due tonalità di blu.
Nota che il gradiente utilizzato per definire la sfumatura ha la proprietà proportional definita come true, in questo modo definiamo gli stop in formato relativo, decisamente più comodo.

Il secondo rettangolo definisce l'area centrale, é molto simile al primo, la differenza più grossa é che non ha un contorno:

Rectangle {
x: 48, y: 106, width: 150, height: 64
fill: LinearGradient {
startX: 0.0, startY: 1.0, endX: 0.0, endY: 0.0,
proportional: true
stops: [
Stop { offset: 0.0, color: Color.web("#99ddff") },
Stop { offset: 1.0, color: Color.web("#337799") }
]
} // fill
}

Il terzo rettangolo definisce l'area in basso:

Rectangle {
x: 48, y: 170, width: 150, height: 25
fill: LinearGradient {
startX: 0.0, startY: 1.0, endX: 0.0, endY: 0.0,
proportional: true
stops: [
Stop { offset: 0.0, color: Color.web("#337799") },
Stop { offset: 1.0, color: Color.web("#99ddff") }
]
} //fill
}

E infine usiamo un quarto rettangolo per incorniciare i tre di cui sopra:

Rectangle {
x: 48, y: 45, width: 150, height: 150
arcWidth: 15, arcHeight: 15,
stroke: Color.web("#337799")
strokeWidth: 5
fill: null
}

Notiamo che questo rettangolo é arrotondato (nota la definizione delle variabili arcWidth e arcHeight diverse da zero) ha un bordo piuttosto spesso (5 pixel) e, soprattutto, non ha nulla al suo interno (la variabile fill é settata a null). Dunque é solo una cornice, che lascia vedere quanto c'é sotto.

Il tasto Play

Abbiamo definito il fondale, ora vogliamo aggiungere un tasto che sarà composto da un cerchio con un triangolo al suo interno, che rappresenta una freccia verso destra. Anzi, per dare un'elegante effetto tridimensionale, di triangoli ne facciamo due, sovrapposti.

Avremo bisogno di altre due classi, Circle e Polygon, che importiamo. Poi aggiungeremo i nostri tre nuovi oggetti al gruppo sulla scena:

...
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
...
Group {
content: [
...
Circle {
centerX: 122 centerY: 122 radius: 38
fill: LinearGradient {startX: 0.0, startY: 1.0, endX: 0.0, endY: 0.0,
proportional: true
stops: [
Stop {offset: 0.0 color: Color.web("#66aacc")},
Stop {offset: 1.0 color: Color.web("#99ddff")}
]
} // fill
stroke: Color.web("#66aacc")
strokeWidth: 2.0
} // circle

Polygon {
points: [142.0, 126.0, 113.0, 108.0, 111.0, 143.0]
fill: Color.web("#337799")
} // lower triangle

Polygon {
points: [142.0, 123.0, 110.0, 105.0, 110.0, 140.0]
fill: Color.web("#ffffff")
} // upper triangle
]

E questo é tutto per il nostro esempio in ambiente comune.

Desktop Profile

L'ambiente desktop permette di sbizzarrirsi un po' di più con gli effetti visuali.

Una cosa che possiamo fare, é ottenere l'effetto tridimensionale sul triangolo senza raddoppiare gli oggetti, ma aggiungendo al triangolo una ombreggiatura.

Effetto DropShadow

Importiamo la classe DropShadow e ridefiniamo il nostro triangolo usando un solo poligono definito come segue:

import javafx.scene.effect.DropShadow;
...
Polygon {
points: [142.0, 123.0, 110.0, 105.0, 110.0, 140.0]
fill: Color.web("#ffffff")
effect: DropShadow {
color: Color.web("#337799")
offsetX: 2, offsetY: 5
}
}


Effetto reflection

Come ultima cosa, aggiungiamo un riflesso alla nostra immagine, importiamo la classe Reflection, e aggiungiamo un effetto al nostro gruppo di oggetti sulla scena:

import javafx.scene.effect.Reflection;
Group {
content: [
...
]
effect: Reflection { fraction: 0.5 topOpacity: 0.5 topOffset: 0.5 }
} //Group

Come riferiment, lascio qui a seguire il codice completo per lo script di questa lezione:

package uiTutorial;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.Group;
import javafx.scene.shape.Rectangle;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.scene.effect.DropShadow; // for desktop enhancement
import javafx.scene.effect.Reflection; // for desktop enhancement

Stage {
title: "Play Button"

scene: Scene {
width: 250, height: 350
fill: Color.WHITE
content: Group {
content: [
Rectangle {
x: 48, y: 46, width: 150, height: 59
stroke: Color.GREEN
fill: LinearGradient {
startX: 0.0, startY: 1.0, endX: 0.0, endY: 0.0,
proportional: true
stops: [
Stop { offset: 0.0, color: Color.web("#aaeeff") },
Stop { offset: 1.0, color: Color.web("#66aacc") }
]
} // fill
} // top rectangle

Rectangle {
x: 48, y: 106, width: 150, height: 64
fill: LinearGradient {
startX: 0.0, startY: 1.0, endX: 0.0, endY: 0.0,
proportional: true
stops: [
Stop { offset: 0.0, color: Color.web("#99ddff") },
Stop { offset: 1.0, color: Color.web("#337799") }
]
} // fill
} // central rectangle

Rectangle {
x: 48, y: 170, width: 150, height: 25
fill: LinearGradient {
startX: 0.0, startY: 1.0, endX: 0.0, endY: 0.0,
proportional: true
stops: [
Stop { offset: 0.0, color: Color.web("#337799") },
Stop { offset: 1.0, color: Color.web("#99ddff") }
]
} //fill
} // bottom rectangle

Rectangle {
x: 48, y: 45, width: 150, height: 150
arcWidth: 15, arcHeight: 15,
stroke: Color.web("#337799")
strokeWidth: 5
fill: null
} // border rectangle

Circle {
centerX: 122 centerY: 122 radius: 38
fill: LinearGradient {startX: 0.0, startY: 1.0, endX: 0.0, endY: 0.0,
proportional: true
stops: [
Stop {offset: 0.0 color: Color.web("#66aacc")},
Stop {offset: 1.0 color: Color.web("#99ddff")}
]
} // fill
stroke: Color.web("#66aacc")
strokeWidth: 2.0
} // circle

/*
// common profile version for the triangle
Polygon {
points: [142.0, 126.0, 113.0, 108.0, 111.0, 143.0]
fill: Color.web("#337799")
} // lower triangle

Polygon {
points: [142.0, 123.0, 110.0, 105.0, 110.0, 140.0]
fill: Color.web("#ffffff")
} // upper triangle
*/
Polygon {
points: [142.0, 123.0, 110.0, 105.0, 110.0, 140.0]
fill: Color.web("#ffffff")
effect: DropShadow {
color: Color.web("#337799")
offsetX: 2, offsetY: 5
}
} // triangle as desktop enhancement
] // group content

// effect as desktop enhancement
effect: Reflection { fraction: 0.5 topOpacity: 0.5 topOffset: 0.5 }
} //Group
} //Scene
}

Nessun commento:

Posta un commento