SlideShare a Scribd company logo
1 of 46
Download to read offline
7
Transitions for Windows, Dialogs and
Perspectives (ch07-rev.01-15072018 firmani
nelson)
Le classi che forniscono l’animazione in JavaFX si trovano nel pacchetto javafx.animation.
Un’animazione in javaFX si realizza con una variazione delle proprietà associate a un nodo, come dimensioni,
posizione e colore.
Sono controllate da una "timeline" cioè un’arco di tempo che fornisce la capacità di aggiornare i valori delle
proprietà lungo la progressione del tempo.
Le timeline usano i keyframes (fotogrammi chiave) per definire le variabili i cui valori devono essere fissati a
istanti specifici dell’animazione. Poi il sistema attraverso le interpolazioni che occorrono tra un key frame e
l’altro può eseguire automaticamente l’animazione.
E' possibile animare qualsiasi nodo per produrre effetti di dissolvenza, traslazione, rotazione, etc.
Per farlo, è necessario istanziare la rispettiva classe di transizione (animazione) che deve essere applicata al
nodo, impostare le proprietà della transizione e infine, eseguire la transizione usando il metodo play () della
classe Animation.
Esistono inoltre metodi per interrompere, sospendere, riprendere, invertire o ripetere movimenti quando
richiesto.
Figura 7.1. UML javafx.animation.Animation
FadeTransition
graduale scomparsa di un nodo modificando la proprietà di opacità da un valore iniziale a un valore finale
con una durata specificata dalla proprietà duration
ParallelTransition
Esegue più transizioni simultaneamente.
PathTransition
sposta un nodo lungo un percorso geometrico aggiornando le proprietà translateX e translateY della
proprietà del nodo con durata specificata dalla proprietà duration
149
SequentialTransition
Esegue più transizioni uno dopo l’altra.
FillTransition
modifica il colore di riempimento di una forma da un colore iniziale a un colore finale secondo una durata
specificata
PauseTransition
attende la scadenza del valore della proprietà duration e quindi esegue il gestore eventi assegnato alla
sua proprietà onFinished
RotateTransition
ruota un nodo attorno al suo centro variando la proprietà di rotazione del suo nodo da un valore iniziale a
un valore finale (entrambi in gradi) con durata specificata dalla proprietà duration.
ScaleTransition
cambia la proprietà scaleX , scaleY e Scalez degli oggetti di un nodo da un valore iniziale a un valore finale
secondo una durata specificata.
TranslateTransition
modifica le proprietà translateX , translateY e translateZ di una proprietà del nodo da un valore iniziale ad
un valore finale per la durata specificata dalla proprietà duration
I valori delle proprietà coinvolte tra i keyframes vengono definite automaticamente mediante interpolazione.
E' possibile utilizzare varie implementazioni integrate della classe Interpolator oppure implementare il proprio
Interpolatore per ottenere un comportamento di interpolazione personalizzato.
Figura 7.2. UML javafx.animation.Interpolator
JavaFX fornisce diversi interpolatori utilizzabili per creare effetti diversi nell’animazione.
150
Per impostazione predefinita, JavaFX utilizza l’interpolazione lineare per calcolare i valori delle proprietà.
Interpolator.LINEAR
è l’interpolatore di default. Il cambiamento nel valore della variabile associata è proporzionale allo scorrere
del tempo;
interpolator.DISCRETE
questo interpolatore permette alla variabile di conservare il suo valore iniziale fino alla fine del keyframe,
e a quel punto viene assegnato il valore;
Interpolator.EASIN
ha le stesse proprietà dell’Interpolator.LINEAR ma il valore cambia più lentamente all’avvio del keyframe;
Interpolator.EASEOUT
ha le stesse proprietà dell’Interpolator.LINEAR ma il valore cambia più lentamente alla fine del keyframe;
Interpolaor.EASEBOTH
ha le stesse proprietà dell’Interpolator.LINEAR ma il valore cambia più lentamente all’inizio e alla fine del
keyframe;
Interpolator.SPLINE
il modo in cui il valore della variabile cambia dipende da una curva spline associata con l’Interpolator.
151
Windows
Nelle applicazioni Eclipse RCP con JavaFX la transizione da finestra aperta a finestra
chiusa e viceversa, l’animazione di finestre di dialogo e la transizione di prospettive
(perspective) avvengono attraverso l’implementazione di servizi OSGi.
7.1. Windows
La transizione da finestra aperta a finestra chiusa e viceversa avviene attraverso l’implementazione di un
servizio OSGi
la cui interfaccia esposta dal bundle
org.eclipse.fx.ui.workbench.renderers.base.services è
org.eclipse.fx.ui.workbench.renderers.base.services.WindowTransitionService<Stage>
I servizi OSGi possono essere definiti in modo dichiarativi in un file xml.
L’IDE eclipse attraverso una procedura guidata permette la creazione di un file xml con le informazioni
necessarie per la definizione del componente (servizio OSGi).
Elementi essenziali del file sono il nome della classe dell’istanza del componente e l’interfaccia del servizio
fornito.
La procedura guidata inoltre aggiunge il riferimento di questo file al file MANIFEST.MF
OSGI-INF/services/window-transition.xml.
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/
v1.1.0" enabled="true" name="it.nelson.xbrl.client.app.WindowTransition">
<implementation class="it.nelson.xbrl.client.app.WindowTransition"/>
<service>
<provide interface="org.eclipse.fx.ui.workbench.renderers.base.services.WindowTransitionService"/
>
</service>
</scr:component>
Nel MANIFEST.MF alla voce Service-Component c'è il riferimento ai file che descrivono i componenti, questi
file in genere si creano in una cartella di nome OSGI-INF.
META-INF/MANIFEST.MF.
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: My Sample App
Bundle-SymbolicName: it.nelson.xbrl.client.app;singleton:=true
Bundle-Version: 1.0.1.qualifier
Require-Bundle: org.eclipse.fx.ui.workbench.fx,
...
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: javax.inject;version="1.0.0",
...
Bundle-ActivationPolicy: lazy
Service-Component: OSGI-INF/services/window-transition.xml
Creazione del componente (servizio) OSGi attraverso la procedura guidata disponibile dall’ide eclipse.
152
Windows
Figura 7.3. Wizard per la creazione del servizio window transition
Creazione della classe WindowTransition.
Figura 7.4. Creazione della classe di implementazione del servizio
Riferimento alla classe WindowTransition.
153
Windows
Figura 7.5. Riferimento alla classe del servizio
Figura 7.6. Descrizione xml del servizio
La descrizione del componente attraverso il file xml contiene tutte le informazioni del servizio, nome, classe
e interfaccia del servizio
154
Windows
Figura 7.7. Sezione Services per selezionare l’interfaccia del servizio da implementare
org.eclipse.fx.ui.workbench.renderers.base.services.WindowTransitionService come interfaccia del
servizio
Figura 7.8. Selezionata l’interfaccia WindowsTransitionService
155
Windows
Figura 7.9. file window-transition.xml
Implementazione della classe WindowTransition:
La transizione (animazione) avviene attraverso l’implementazione del metodo
animate(@NonNull C window, @NonNull Runnable finished)
del tipo
AnimationDelegate<Node>
definito come interfaccia annidata dell’interfaccia
WindowTransitionService<Node>
Figura 7.10. UML WindowTransition
156
Windows
Figura 7.11. La classe WindowTransition
Figura 7.12. La classe StageFadeTransition
157
Windows
Figura 7.13. Warning
Figura 7.14. Suppress warning
158
Windows
Figura 7.15. Verifica fade-transition apertura window
Possibilità di abilitare o disabilitare il servizio dal file descrittore del servizio.
Figura 7.16. Abilitare/Disabilitare il servizio window transition
159
Windows
Figura 7.17. Servizio window transition disabilitato
Dunque in sintesi il file window-transition.xml definisce un componente di nome
it.nelson.xbrl.client.app.WindowTransition
che fornisce un servizio al OSGi-service-registry per l’interfaccia
org.eclipse.fx.ui.workbench.renderers.base.services.WindowTransitionService.
Servizio implementato dalla classe it.nelson.xbrl.client.app.WindowTransition (non è necessario che il nome
della classe e il nome del componente coincidono) il cui sorgente è:
/it.nelson.xbrl.client.app/src/it/nelson/xbrl/client/app/WindowTransition.java.
package it.nelson.xbrl.client.app;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.fx.ui.workbench.renderers.base.services.WindowTransitionService;
import org.osgi.service.component.annotations.Component;
import javafx.stage.Stage;
import javafx.util.Duration;
@SuppressWarnings("restriction")
@Component
public class WindowTransition implements WindowTransitionService<Stage> {
@Override
public AnimationDelegate<Stage> getShowDelegate(
MWindow window) {
return new AnimationDelegate<Stage>() {
@Override
public void animate(Stage window, Runnable finished) {
window.setOpacity(0);
window.show();
StageFadeTransition fade = new StageFadeTransition(window, 0, 1, Duration.millis(3000)); //fade
transition di 3 secondi
fade.setOnFinished( e -> finished.run());
fade.play();
}
};
}
@Override
public AnimationDelegate<Stage> getHideDelegate(
MWindow window) {
return null;
}
}
160
Dialogs
/it.nelson.xbrl.client.app/src/it/nelson/xbrl/client/app/StageFadeTransition.java.
package it.nelson.xbrl.client.app;
import javafx.animation.Transition;
import javafx.stage.Stage;
import javafx.util.Duration;
public class StageFadeTransition extends Transition {
private final Stage stage;
private final double start;
private final double delta;
public StageFadeTransition(Stage stage, double start, double end, Duration duration) {
this.stage = stage;
this.start = start;
this.delta = end - start;
setCycleDuration(duration);
}
@Override
protected void interpolate(double frac) {
double v = start + frac * delta;
final double newOpacity = Math.max(0.0,
Math.min(v, 1.0));
stage.setOpacity(newOpacity);
}
}
7.2. Dialogs
Il sistema di dialogo è costruito attorno alla classe base org.eclipse.fx.ui.controls.dialog.Dialog con le classi
derivate:
1. TitleAreaDialog (finestra di dialogo con un’area riservata in alto per visualizzare le informazioni)
2. MessageDialog (QUESTION, INFORMATION, WARNING, ERROR, CONFIRM, QUESTION_CANCEL)
Le applicazioni eclipse RCP (E4) con javafx possono utilizzare le finestre di dialogo attraverso un nuovo servizio
denominato
org.eclipse.fx.ui.services.dialog.LightWeightDialogService
così l’apertura di una finestra di dialogo può essere eseguita con:
@Execute
public void openDialog(LightWeightDialogService service) {
MyDialog d = new MyDialog();
service.openDialog(d, ModalityScope.WINDOW);
}
161
Dialogs
Figura 7.18. UML LightWeightDialogService
Figura 7.19. UML Dialog
La classe TestDialogHandler.
package it.nelson.xbrl.client.app.handlers;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.fx.ui.services.dialog.LightWeightDialogService;
import org.eclipse.fx.ui.services.dialog.LightWeightDialogService.ModalityScope;
public class TestDialogHandler {
@Execute
public void execute(LightWeightDialogService dialogService) {
MyDialog myDialog = new MyDialog("frame title", "title", "message");
dialogService.openDialog(myDialog, ModalityScope.WINDOW);
}
}
La classe myDialog.
package it.nelson.xbrl.client.app.handlers;
import org.eclipse.fx.ui.controls.dialog.TitleAreaDialog;
import javafx.scene.control.Button;
162
Dialogs
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
@SuppressWarnings("restriction")
public class MyDialog extends TitleAreaDialog {
public MyDialog(String frameTitle, String title, String message) {
super(frameTitle, title, message);
// nodo che riempie la client area
Label lbtop = new Label("Client area border layout (top)");
Button btnr = new Button("Right");
Button btnl = new Button("Left");
Button btnc = new Button("Center");
Hyperlink link = new Hyperlink("Bottom");
BorderPane clientArea = new BorderPane(btnc, lbtop, btnr, link, btnl);
//
setClientArea(clientArea);
addDefaultButtons();
// setMaxHeight(500);
setPrefHeight(400);
setPrefWidth(500);
setId("test-dialog"); // id selector template css
}
}
Css dialog.
/* Css dialog */
.efx-dialog-title-image {
-fx-image: url(icons/64/applications-system.png);
}
#open-project-dialog .efx-dialog-title-image {
-fx-image: url(icons/64/prj_obj.png);
}
#open-project-dialog .efx-dialog-messageArea-area {
-fx-background-color: rgb(192.0,192.0,192.0) ;
}
#test-dialog .efx-dialog-title-image {
-fx-image: url(icons/64/application-x-java.png);
}
#test-dialog .efx-dialog-graphic-container {
-fx-background-color: blue ;
}
#test-dialog .efx-dialog-messageArea-area {
-fx-background-color: red ;
}
#test-dialog .efx-dialog-title {
/* -fx-background-color: beige ; */
-fx-font-size: 16pt;
163
Dialogs
}
#test-dialog .efx-dialog-title-message {
-fx-font-size: 14pt;
}
#test-dialog .efx-dialog-title-font-icon {
}
Figura 7.20. Finestra MyDialog di tipo TitleAreaDialog
Creazione di una finestra di dialogo di tipo TitleAreaDialog con una client area costituita da una lista di elementi.
Figura 7.21. Menu, comando e gestore dell’apertura della finestra di esempio
164
Dialogs
Figura 7.22. Classe apertura finestra di dialogo
Figura 7.23. Css della finestra di dialogo
165
Dialogs
Figura 7.24. Finestra di dialogo in esecuzione
Mentre la classe TitleAreaDialog consente di creare facilmente una finestra di dialogo di tipo pop-up con uno
spazio riservato per fornire feedback all’utente e creare un proprio layout,
la classe MessageDialog consente all’utente di essere avvisato di qualcosa o confermare una domanda tipo
yes/no/cancel.
Tutte le finestre di dialogo (TitleAreaDialog e MessageDialog) create sono modali cioè blocca il thread corrente
fino a quando l’interazione con l’utente non è stata completata.
Esempio di finestra di conferma.
package it.nelson.xbrl.client.app.lifecycle;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.fx.ui.dialogs.MessageDialog;
import org.eclipse.fx.ui.dialogs.MessageDialog.ConfirmResult;
import org.eclipse.fx.ui.workbench.renderers.base.widget.WWindow;
import org.eclipse.fx.ui.workbench.services.lifecycle.annotation.PreClose;
import org.eclipse.fx.ui.workbench.services.lifecycle.annotation.PreShow;
import javafx.stage.Stage;
public class LifeCycle {
@PreShow
public void execute() {
System.err.println("PreShow");
}
@PreClose
public boolean ph(MWindow win) {
System.err.println("PreClose");
166
Dialogs
if (MessageDialog.openConfirmDialog((Stage) ((WWindow) win.getWidget()).getWidget(), "Messaggio
di conferma",
"Conferma chiusura scheda?") == ConfirmResult.OK)
return true;
else
return false;
}
}
Figura 7.25. Esempio di finestra di conferma
Esempio di finestra di informazione.
...
@FXML
void actSave(ActionEvent event) {
bookService.addBook(DATASOURCE.get(idListView.getSelectionModel().getSelectedIndex()));
MessageDialog.openInformationDialog(stage, "Conferma",
"Salvato libro con id= " +
DATASOURCE.get(idListView.getSelectionModel().getSelectedIndex()).getId());
}
...
167
Dialogs
Figura 7.26. Esempio di finestra di informazione
Esempio di finestra di errore.
...
try {
bookService.init();
} catch (Throwable e) {
System.err.println("Impossibile stabilire connessione con il DB");
MessageDialog.openErrorDialog(stage, "ERRORE DI CONNESSIONE",
"Non posso creare EntityManagerFactory: " + e.getMessage());
throw new ExceptionInInitializerError(e);
}
...
168
Dialogs
Figura 7.27. Esempio di finestra di errore
Mentre il servizio di dialogo consente di aprire una finestra di dialogo e controllare la sua modalità, c'è un
secondo servizio che è in grado di controllare come viene mostrata / nascosta una finestra di dialogo.
Di default la finestra di dialogo è semplicemente mostrata e nascosta ma si possono aggiungere anche delle
animazioni come mostrato di seguito
La finestra di dialogo può essere aperta in modo animato attraverso l’implementazione di un servizio OSGi la
cui interfaccia esposta dal bundle
org.eclipse.fx.ui.workbench.renderers.fx.services
è
org.eclipse.fx.ui.workbench.renderers.fx.services.LightweightDialogTransitionService
Il package package org.eclipse.fx.ui.workbench.renderers.fx.services fornisce delle classi di transizioni delle
finestre di dialogo
con l’implementazioni di transizioni (animazioni) predefinite:
1. FadeDialogTransitionService: classe astratta da ereditare per implementare una transizione della finestra
di dialogo per dissolvenza, la classe derivata può riscrivere i metodi ereditati per variare le proprietà
dell’animazione:
• protected void configureFadeIn(FadeTransition transition)
• protected void configureFadeOut(FadeTransition transition)
2. FlyInTransitionService: classe concreta da ereditare per implementare transizione per variazione della
posizione verticale (apertura dall’alto verso il basso chiusura dal basso verso l’alto)
169
Dialogs
Figura 7.28. UML DialogTransitionService
Esempio di implementazione del servizio di trasparenza finestre di dialogo
package it.nelson.xbrl.client.app;
import org.eclipse.fx.ui.workbench.renderers.fx.services.FadeDialogTranstionService;
import org.eclipse.fx.ui.workbench.renderers.fx.services.LightweightDialogTransitionService;
import org.osgi.service.component.annotations.Component;
import javafx.animation.FadeTransition;
import javafx.animation.Interpolator;
import javafx.util.Duration;
@Component(service = LightweightDialogTransitionService.class)
public class DialogTransition extends FadeDialogTranstionService {
@Override
protected void configureFadeIn(FadeTransition transition) {
super.configureFadeIn(transition);
transition.setInterpolator(Interpolator.EASE_IN);
transition.setDuration(Duration.millis(600));
}
@Override
protected void configureFadeOut(FadeTransition transition) {
super.configureFadeOut(transition);
transition.setInterpolator(Interpolator.EASE_OUT);
transition.setDuration(Duration.millis(600));
}
}
170
Dialogs
Figura 7.29. Definizione servizio transizione della finestra di dialogo
Figura 7.30. Nome e riferimento della classe del servizio
171
Dialogs
Figura 7.31. Ricerca dell’interfaccia che fornisce il servizio
Figura 7.32. Interfaccia che fornisce il servizio
172
Dialogs
Figura 7.33. Classe che implementa il servizio di transizione per dissolvenza
FadeDialogTranstionService è la classe che implementa la transizione per dissolvenza, la classe derivata può
riscrivere i metodi ereditati:
• protected void configureFadeIn(FadeTransition transition)
• protected void configureFadeOut(FadeTransition transition)
Figura 7.34. Riscrittura metodi ereditati
173
Dialogs
Figura 7.35. Fade transition della finestra di dialogo in esecuzione
Di seguito l’altra animazione predefinita della finestra di dialogo implementata attraverso la classe
FlyInTransitionService
package it.nelson.xbrl.client.app;
import org.eclipse.fx.ui.workbench.renderers.fx.services.FlyInTransitionService;
import org.eclipse.fx.ui.workbench.renderers.fx.services.LightweightDialogTransitionService;
import org.osgi.service.component.annotations.Component;
@Component(property = { "service.ranking:Integer=-1" })
public class FlyinTransitionServiceImpl extends FlyInTransitionService implements
LightweightDialogTransitionService {
}
174
Dialogs
Figura 7.36. Nome e riferimento della classe del servizio
Figura 7.37. La classe che implementa il servizio
175
Dialogs
Figura 7.38. Proprietà ranking del servizio
Figura 7.39. Interfaccia che fornisce il servizio
176
Dialogs
Figura 7.40. Finestra di dialogo con animazione predefinita dalla classe FlyInTransitionService
Implementazione di una animazione non predefinita.
Figura 7.41. La classe che implementa il servizio
Figura 7.42. Metodi da implementare segnati dall’interfaccia
177
Dialogs
Figura 7.43. Metodi da implementare
Figura 7.44. Implementazione dei metodi
178
Dialogs
Figura 7.45. Nuovo riferimento di classe nel servizio di transizione della finestra di dialogo
Figura 7.46. Servizio implementato dalla classe MyAnimTransitionServiceImpl
Utilizzando le api di javaFX: fadeTransition e rotateTransition
MyAnimTransitionServiceImpl.java.
package it.nelson.xbrl.client.app;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.fx.ui.workbench.renderers.fx.services.LightweightDialogTransitionService;
import org.osgi.service.component.annotations.Component;
import javafx.animation.FadeTransition;
import javafx.animation.Interpolator;
import javafx.animation.ParallelTransition;
import javafx.animation.RotateTransition;
import javafx.animation.TranslateTransition;
import javafx.scene.Node;
import javafx.scene.layout.Pane;
import javafx.util.Duration;
@Component(property = { "service.ranking:Integer=-1" })
public class MyAnimTransitionServiceImpl implements LightweightDialogTransitionService {
private boolean fadeGrayArea;
@Override
179
Dialogs
public void showDialog(MUIElement container, Pane containerNode, Pane dialogOverlayContainer, Node
grayArea,
Node dialog, Runnable finished) {
FadeTransition fd = new FadeTransition(Duration.millis(4000), dialogOverlayContainer);
fd.setFromValue(0.0);
fd.setToValue(1.0);
TranslateTransition t = new TranslateTransition(Duration.millis(4000), dialog);
t.setFromY(-1 * (dialog.getLayoutY() + dialog.prefHeight(-1)));
t.setFromX(-1 * (dialog.getLayoutX() + dialog.prefWidth(-1)));
t.setToX(0);
t.setToY(0);
t.setInterpolator(Interpolator.EASE_OUT);
if (finished != null) {
t.setOnFinished(e -> {
finished.run();
});
}
ParallelTransition p = new ParallelTransition(t);
if (this.fadeGrayArea) {
p.getChildren().add(fd);
}
p.play();
}
@Override
public void hideDialog(MUIElement container, Pane containerNode, Pane dialogOverlayContainer, Node
grayArea,
Node dialog, Runnable finished) {
RotateTransition r = new RotateTransition(Duration.millis(2000), dialog);
r.setByAngle(180f);
r.setCycleCount(4);
r.setAutoReverse(true);
if (finished != null) {
r.setOnFinished(e -> {
finished.run();
});
}
r.play();
}
}
otteniamo una animazione di tipo rotazione e dissolvenza
180
Dialogs
Figura 7.47. Animazione in esecuzione
Utilizzando le api di javaFX: pathTransition e CubicCurveTo otteniamo una animazione più complessa
@Override
public void hideDialog(MUIElement container, Pane containerNode, Pane dialogOverlayContainer, Node
grayArea,
Node dialog, Runnable finished) {
Path path = new Path();
path.getElements().add(new MoveTo(-30, -30));
path.getElements().add(new CubicCurveTo(400, 0, 400, 100, 200, 100));
path.getElements().add(new CubicCurveTo(0, 100, 0, 240, 400, 240));
PathTransition pathTransition = new PathTransition();
pathTransition.setDuration(Duration.millis(3000));
pathTransition.setPath(path);
pathTransition.setNode(dialog);
pathTransition.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
pathTransition.setCycleCount(2);
pathTransition.setAutoReverse(true);
if (finished != null) {
pathTransition.setOnFinished(e -> {
finished.run();
});
}
pathTransition.play();
}
181
Perspective
Figura 7.48. Animazione in esecuzione
7.3. Perspective
La transizione delle prospettive (perspective) avviene attraverso l’implementazione di un servizio OSGi
la cui interfaccia esposta dal bundle
org.eclipse.fx.ui.workbench.renderers.base.services
è
org.eclipse.fx.ui.workbench.renderers.base.services.PerspectiveTransitionService<BorderPane,Node>
Il package org.eclipse.fx.ui.animation.pagetransition.animation fornisce delle classi di transizioni con
l’implementazioni di transizioni (animazioni) predefinite
Figura 7.49. UML org.eclipse.fx.ui.animation.pagetransition
Quindi per realizzare ad esempio una animazione di una prospettiva che si apre con effetto zoom occorre
definire il servizio OSGi descritto nel file perspective-animation.xml
perspective-animation.xml.
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" enabled="true"
name="it.nelson.xbrl.client.app.PerspectiveAnimation">
<implementation class="it.nelson.xbrl.client.app.PerspectiveAnimation"/>
<service>
<provide interface="org.eclipse.fx.ui.workbench.renderers.base.services.PerspectiveTransitionService"/
>
</service>
182
Perspective
</scr:component>
e la classe it.nelson.xbrl.client.app.PerspectiveAnimation che implementa il servizio:
PerspectiveAnimation.java.
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.fx.ui.animation.pagetransition.animation.ZoomSlideAnimation;
import org.eclipse.fx.ui.workbench.renderers.base.services.PerspectiveTransitionService;
import org.osgi.service.component.annotations.Component;
import javafx.scene.Node;
import javafx.scene.layout.BorderPane;
@SuppressWarnings("restriction")
@Component
public class PerspectiveAnimation implements PerspectiveTransitionService<BorderPane, Node> {
@Override
public AnimationDelegate<BorderPane, Node> getDelegate(MPerspective fromPerspective, MPerspective
toPerspective) {
return new AnimationDelegate<BorderPane, Node>() {
@Override
public void animate(BorderPane container, Node control, Runnable finished) {
ZoomSlideAnimation animation = new ZoomSlideAnimation();
animation.animate(container, control, finished);
}
};
}
}
In figura un esempio di implementazione per la transizione di perspective mediante l’animazione predefinita
PageChangeAnimation.
Figura 7.50. Animazione transizione prospettive
Definizione del servizio OSGi mediante il wizard component definition in plug-in development di eclipse
183
Perspective
Figura 7.51. Servizio perspective animation
Figura 7.52. Definizione del fornitore del servizio
184
Perspective
Figura 7.53. Errore dopo esecuzione
Figura 7.54. Errore causato da una dipendenza non corretta (da rimuovere)
185
Perspective
Figura 7.55. Segnalzione nel codice dopo rimozione dipendenza
Figura 7.56. Package giusto da importare
186
Perspective
Figura 7.57. Codice dopo importazione package
Figura 7.58. Verifica mediante esecuzione
Realizzazione di una animazione di una prospettiva che si apre con effetto non predefinito ma costruito
attraverso una classe che estende la superclasse CenterSwitchAnimation e l’implementazione dei metodi
ereditati attraverso le api javaFX
187
Perspective
Figura 7.59. Descrizione del servizio di animazione nel cambio prospettiva
Figura 7.60. Interfaccia che fornisce il servizio
188
Perspective
Figura 7.61. Descrizione del servizio in xml
Figura 7.62. Classe delegata che implementa l’interfaccia del servizio
Costruzione della classe MyAnimRotate che estende la superclasse CenterSwitchAnimation
189
Perspective
Figura 7.63. Creazione della classe MyAnimRotate
Figura 7.64. Sorgente della classe MyAnimRotate
Implementazione dei metodi ereditati dalla superclasse CenterSwitchAnimation mediante le classi javaFX
RotateTransition e FadeTransition
190
Perspective
Figura 7.65. Implementazione dei metodi ereditati dalla superclasse CenterSwitchAnimation
Figura 7.66. Animazione cambio prospettiva in esecuzione
Animazione più complessa mediante l’implementazione dei metodi ereditati dalla superclasse
CenterSwitchAnimation con le classi javaFX PathTransition e ScaleTransition
191
Perspective
Figura 7.67. Animazione più complessa
192
Perspective
Figura 7.68. Classe che implementa il servizio
Figura 7.69. Animazione in esecuzione
193
194

More Related Content

Similar to eclipse capitolo7: Transitions for Windows, Dialogs and Perspectives

Sviluppo di una piattaforma Client/Server per attività didattiche basate su R...
Sviluppo di una piattaforma Client/Server per attività didattiche basate su R...Sviluppo di una piattaforma Client/Server per attività didattiche basate su R...
Sviluppo di una piattaforma Client/Server per attività didattiche basate su R...Giacomo Delfini
 
Spring Framework
Spring FrameworkSpring Framework
Spring FrameworkNaLUG
 
Eclipse Lifecycle chapter 04
Eclipse Lifecycle chapter 04Eclipse Lifecycle chapter 04
Eclipse Lifecycle chapter 04Nelson Firmani
 
Introduzione a Workflow Foundation
Introduzione a Workflow FoundationIntroduzione a Workflow Foundation
Introduzione a Workflow FoundationDotNetMarche
 
GreenVulcano ESB Technical Overview (ITA)
GreenVulcano ESB Technical Overview (ITA)GreenVulcano ESB Technical Overview (ITA)
GreenVulcano ESB Technical Overview (ITA)greenvulcano
 
Simulatore Grafico Per Reti Ottiche A Pacchetto
Simulatore Grafico Per Reti Ottiche A PacchettoSimulatore Grafico Per Reti Ottiche A Pacchetto
Simulatore Grafico Per Reti Ottiche A PacchettoFedele Mantuano
 
Niccolò Becchi: Introduzione a GWT
Niccolò Becchi: Introduzione a GWTNiccolò Becchi: Introduzione a GWT
Niccolò Becchi: Introduzione a GWTfirenze-gtug
 
Sistemi Context-aware: Esercitazione 3
Sistemi Context-aware: Esercitazione 3Sistemi Context-aware: Esercitazione 3
Sistemi Context-aware: Esercitazione 3Marco Loregian
 
Javascript - 7 | WebMaster & WebDesigner
Javascript - 7 | WebMaster & WebDesignerJavascript - 7 | WebMaster & WebDesigner
Javascript - 7 | WebMaster & WebDesignerMatteo Magni
 
Modulo 6 Spring Framework Core E Aop
Modulo 6 Spring Framework Core E AopModulo 6 Spring Framework Core E Aop
Modulo 6 Spring Framework Core E Aopjdksrl
 
Lezione 9: Web Service in Java
Lezione 9: Web Service in JavaLezione 9: Web Service in Java
Lezione 9: Web Service in JavaAndrea Della Corte
 
Realizzare applicazioni cross-platform con Xamarin e il pattern MVVM
Realizzare applicazioni cross-platform con Xamarin e il pattern MVVMRealizzare applicazioni cross-platform con Xamarin e il pattern MVVM
Realizzare applicazioni cross-platform con Xamarin e il pattern MVVMCodemotion
 
Microservices architecture & Service Fabric
Microservices architecture & Service FabricMicroservices architecture & Service Fabric
Microservices architecture & Service FabricMassimo Bonanni
 
Sviluppo di applicazioni in E(fx)clipse capitolo 02-rev01-20072018
Sviluppo di applicazioni in E(fx)clipse capitolo 02-rev01-20072018Sviluppo di applicazioni in E(fx)clipse capitolo 02-rev01-20072018
Sviluppo di applicazioni in E(fx)clipse capitolo 02-rev01-20072018Nelson Firmani
 

Similar to eclipse capitolo7: Transitions for Windows, Dialogs and Perspectives (20)

Sviluppo di una piattaforma Client/Server per attività didattiche basate su R...
Sviluppo di una piattaforma Client/Server per attività didattiche basate su R...Sviluppo di una piattaforma Client/Server per attività didattiche basate su R...
Sviluppo di una piattaforma Client/Server per attività didattiche basate su R...
 
Java lezione 14
Java lezione 14Java lezione 14
Java lezione 14
 
Spring Framework
Spring FrameworkSpring Framework
Spring Framework
 
Eclipse Lifecycle chapter 04
Eclipse Lifecycle chapter 04Eclipse Lifecycle chapter 04
Eclipse Lifecycle chapter 04
 
Introduzione a Workflow Foundation
Introduzione a Workflow FoundationIntroduzione a Workflow Foundation
Introduzione a Workflow Foundation
 
DDive11 - xpages
DDive11 - xpagesDDive11 - xpages
DDive11 - xpages
 
GreenVulcano ESB Technical Overview (ITA)
GreenVulcano ESB Technical Overview (ITA)GreenVulcano ESB Technical Overview (ITA)
GreenVulcano ESB Technical Overview (ITA)
 
Simulatore Grafico Per Reti Ottiche A Pacchetto
Simulatore Grafico Per Reti Ottiche A PacchettoSimulatore Grafico Per Reti Ottiche A Pacchetto
Simulatore Grafico Per Reti Ottiche A Pacchetto
 
Niccolò Becchi: Introduzione a GWT
Niccolò Becchi: Introduzione a GWTNiccolò Becchi: Introduzione a GWT
Niccolò Becchi: Introduzione a GWT
 
Sistemi Context-aware: Esercitazione 3
Sistemi Context-aware: Esercitazione 3Sistemi Context-aware: Esercitazione 3
Sistemi Context-aware: Esercitazione 3
 
Introduzione a Struts
Introduzione a StrutsIntroduzione a Struts
Introduzione a Struts
 
Javascript - 7 | WebMaster & WebDesigner
Javascript - 7 | WebMaster & WebDesignerJavascript - 7 | WebMaster & WebDesigner
Javascript - 7 | WebMaster & WebDesigner
 
Modulo 6 Spring Framework Core E Aop
Modulo 6 Spring Framework Core E AopModulo 6 Spring Framework Core E Aop
Modulo 6 Spring Framework Core E Aop
 
Lezione 9: Web Service in Java
Lezione 9: Web Service in JavaLezione 9: Web Service in Java
Lezione 9: Web Service in Java
 
Realizzare applicazioni cross-platform con Xamarin e il pattern MVVM
Realizzare applicazioni cross-platform con Xamarin e il pattern MVVMRealizzare applicazioni cross-platform con Xamarin e il pattern MVVM
Realizzare applicazioni cross-platform con Xamarin e il pattern MVVM
 
Many Designs Elements
Many Designs ElementsMany Designs Elements
Many Designs Elements
 
Microservices architecture & Service Fabric
Microservices architecture & Service FabricMicroservices architecture & Service Fabric
Microservices architecture & Service Fabric
 
Sviluppo di applicazioni in E(fx)clipse capitolo 02-rev01-20072018
Sviluppo di applicazioni in E(fx)clipse capitolo 02-rev01-20072018Sviluppo di applicazioni in E(fx)clipse capitolo 02-rev01-20072018
Sviluppo di applicazioni in E(fx)clipse capitolo 02-rev01-20072018
 
introduzione a symfony 2
introduzione a symfony 2 introduzione a symfony 2
introduzione a symfony 2
 
Introduzione WPF
Introduzione WPFIntroduzione WPF
Introduzione WPF
 

More from Nelson Firmani

Layer di persistenza in una applicazione Eclipse RCP
Layer di persistenza in una applicazione Eclipse RCPLayer di persistenza in una applicazione Eclipse RCP
Layer di persistenza in una applicazione Eclipse RCPNelson Firmani
 
Design pattern template method
Design pattern template methodDesign pattern template method
Design pattern template methodNelson Firmani
 
Modelli di linee di trasmissione nelson firmani
Modelli di linee di trasmissione   nelson firmaniModelli di linee di trasmissione   nelson firmani
Modelli di linee di trasmissione nelson firmaniNelson Firmani
 
documento sistema informativo ambulatorio veterinario on-line
documento sistema informativo ambulatorio veterinario on-linedocumento sistema informativo ambulatorio veterinario on-line
documento sistema informativo ambulatorio veterinario on-lineNelson Firmani
 
REALIZZAZIONE DEL PROGETTO CINEMA ON-LINE CineWeb
REALIZZAZIONE DEL PROGETTO CINEMA ON-LINE CineWebREALIZZAZIONE DEL PROGETTO CINEMA ON-LINE CineWeb
REALIZZAZIONE DEL PROGETTO CINEMA ON-LINE CineWebNelson Firmani
 
REALIZZAZIONE DEL PROGETTO AMBULATORIO VETERINARIO ON-LINE
REALIZZAZIONE DEL PROGETTO AMBULATORIO VETERINARIO ON-LINEREALIZZAZIONE DEL PROGETTO AMBULATORIO VETERINARIO ON-LINE
REALIZZAZIONE DEL PROGETTO AMBULATORIO VETERINARIO ON-LINENelson Firmani
 
Progettazione di un convertitore analogico digitale in architettura multistadio
Progettazione di un convertitore analogico digitale in architettura multistadioProgettazione di un convertitore analogico digitale in architettura multistadio
Progettazione di un convertitore analogico digitale in architettura multistadioNelson Firmani
 
La gestione degli eventi e tecniche implementative
La gestione degli eventi e tecniche implementativeLa gestione degli eventi e tecniche implementative
La gestione degli eventi e tecniche implementativeNelson Firmani
 

More from Nelson Firmani (10)

Layer di persistenza in una applicazione Eclipse RCP
Layer di persistenza in una applicazione Eclipse RCPLayer di persistenza in una applicazione Eclipse RCP
Layer di persistenza in una applicazione Eclipse RCP
 
Design pattern template method
Design pattern template methodDesign pattern template method
Design pattern template method
 
Modelli di linee di trasmissione nelson firmani
Modelli di linee di trasmissione   nelson firmaniModelli di linee di trasmissione   nelson firmani
Modelli di linee di trasmissione nelson firmani
 
Cloud computing
Cloud computingCloud computing
Cloud computing
 
documento sistema informativo ambulatorio veterinario on-line
documento sistema informativo ambulatorio veterinario on-linedocumento sistema informativo ambulatorio veterinario on-line
documento sistema informativo ambulatorio veterinario on-line
 
REALIZZAZIONE DEL PROGETTO CINEMA ON-LINE CineWeb
REALIZZAZIONE DEL PROGETTO CINEMA ON-LINE CineWebREALIZZAZIONE DEL PROGETTO CINEMA ON-LINE CineWeb
REALIZZAZIONE DEL PROGETTO CINEMA ON-LINE CineWeb
 
REALIZZAZIONE DEL PROGETTO AMBULATORIO VETERINARIO ON-LINE
REALIZZAZIONE DEL PROGETTO AMBULATORIO VETERINARIO ON-LINEREALIZZAZIONE DEL PROGETTO AMBULATORIO VETERINARIO ON-LINE
REALIZZAZIONE DEL PROGETTO AMBULATORIO VETERINARIO ON-LINE
 
Progettazione di un convertitore analogico digitale in architettura multistadio
Progettazione di un convertitore analogico digitale in architettura multistadioProgettazione di un convertitore analogico digitale in architettura multistadio
Progettazione di un convertitore analogico digitale in architettura multistadio
 
La gestione degli eventi e tecniche implementative
La gestione degli eventi e tecniche implementativeLa gestione degli eventi e tecniche implementative
La gestione degli eventi e tecniche implementative
 
Web services
Web servicesWeb services
Web services
 

Recently uploaded

Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...Associazione Digital Days
 
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...Associazione Digital Days
 
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...Associazione Digital Days
 
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...Associazione Digital Days
 
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”Associazione Digital Days
 
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...Associazione Digital Days
 
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...Associazione Digital Days
 
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...Associazione Digital Days
 
Programma Biennale Tecnologia 2024 Torino
Programma Biennale Tecnologia 2024 TorinoProgramma Biennale Tecnologia 2024 Torino
Programma Biennale Tecnologia 2024 TorinoQuotidiano Piemontese
 

Recently uploaded (9)

Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
Mael Chiabrera, Software Developer; Viola Bongini, Digital Experience Designe...
 
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
Daniele Lunassi, CEO & Head of Design @Eye Studios – “Creare prodotti e servi...
 
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
Alessandro Nasi, COO @Djungle Studio – “Cosa delegheresti alla copia di te st...
 
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
Gabriele Mittica, CEO @Corley Cloud – “Come creare un’azienda “nativa in clou...
 
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
Edoardo Di Pietro – “Virtual Influencer vs Umano: Rubiamo il lavoro all’AI”
 
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
Luigi Di Carlo, CEO & Founder @Evometrika srl – “Ruolo della computer vision ...
 
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
Alessio Mazzotti, Aaron Brancotti; Writer, Screenwriter, Director, UX, Autore...
 
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
Federico Bottino, Lead Venture Builder – “Riflessioni sull’Innovazione: La Cu...
 
Programma Biennale Tecnologia 2024 Torino
Programma Biennale Tecnologia 2024 TorinoProgramma Biennale Tecnologia 2024 Torino
Programma Biennale Tecnologia 2024 Torino
 

eclipse capitolo7: Transitions for Windows, Dialogs and Perspectives

  • 1. 7 Transitions for Windows, Dialogs and Perspectives (ch07-rev.01-15072018 firmani nelson) Le classi che forniscono l’animazione in JavaFX si trovano nel pacchetto javafx.animation. Un’animazione in javaFX si realizza con una variazione delle proprietà associate a un nodo, come dimensioni, posizione e colore. Sono controllate da una "timeline" cioè un’arco di tempo che fornisce la capacità di aggiornare i valori delle proprietà lungo la progressione del tempo. Le timeline usano i keyframes (fotogrammi chiave) per definire le variabili i cui valori devono essere fissati a istanti specifici dell’animazione. Poi il sistema attraverso le interpolazioni che occorrono tra un key frame e l’altro può eseguire automaticamente l’animazione. E' possibile animare qualsiasi nodo per produrre effetti di dissolvenza, traslazione, rotazione, etc. Per farlo, è necessario istanziare la rispettiva classe di transizione (animazione) che deve essere applicata al nodo, impostare le proprietà della transizione e infine, eseguire la transizione usando il metodo play () della classe Animation. Esistono inoltre metodi per interrompere, sospendere, riprendere, invertire o ripetere movimenti quando richiesto. Figura 7.1. UML javafx.animation.Animation FadeTransition graduale scomparsa di un nodo modificando la proprietà di opacità da un valore iniziale a un valore finale con una durata specificata dalla proprietà duration ParallelTransition Esegue più transizioni simultaneamente. PathTransition sposta un nodo lungo un percorso geometrico aggiornando le proprietà translateX e translateY della proprietà del nodo con durata specificata dalla proprietà duration 149
  • 2. SequentialTransition Esegue più transizioni uno dopo l’altra. FillTransition modifica il colore di riempimento di una forma da un colore iniziale a un colore finale secondo una durata specificata PauseTransition attende la scadenza del valore della proprietà duration e quindi esegue il gestore eventi assegnato alla sua proprietà onFinished RotateTransition ruota un nodo attorno al suo centro variando la proprietà di rotazione del suo nodo da un valore iniziale a un valore finale (entrambi in gradi) con durata specificata dalla proprietà duration. ScaleTransition cambia la proprietà scaleX , scaleY e Scalez degli oggetti di un nodo da un valore iniziale a un valore finale secondo una durata specificata. TranslateTransition modifica le proprietà translateX , translateY e translateZ di una proprietà del nodo da un valore iniziale ad un valore finale per la durata specificata dalla proprietà duration I valori delle proprietà coinvolte tra i keyframes vengono definite automaticamente mediante interpolazione. E' possibile utilizzare varie implementazioni integrate della classe Interpolator oppure implementare il proprio Interpolatore per ottenere un comportamento di interpolazione personalizzato. Figura 7.2. UML javafx.animation.Interpolator JavaFX fornisce diversi interpolatori utilizzabili per creare effetti diversi nell’animazione. 150
  • 3. Per impostazione predefinita, JavaFX utilizza l’interpolazione lineare per calcolare i valori delle proprietà. Interpolator.LINEAR è l’interpolatore di default. Il cambiamento nel valore della variabile associata è proporzionale allo scorrere del tempo; interpolator.DISCRETE questo interpolatore permette alla variabile di conservare il suo valore iniziale fino alla fine del keyframe, e a quel punto viene assegnato il valore; Interpolator.EASIN ha le stesse proprietà dell’Interpolator.LINEAR ma il valore cambia più lentamente all’avvio del keyframe; Interpolator.EASEOUT ha le stesse proprietà dell’Interpolator.LINEAR ma il valore cambia più lentamente alla fine del keyframe; Interpolaor.EASEBOTH ha le stesse proprietà dell’Interpolator.LINEAR ma il valore cambia più lentamente all’inizio e alla fine del keyframe; Interpolator.SPLINE il modo in cui il valore della variabile cambia dipende da una curva spline associata con l’Interpolator. 151
  • 4. Windows Nelle applicazioni Eclipse RCP con JavaFX la transizione da finestra aperta a finestra chiusa e viceversa, l’animazione di finestre di dialogo e la transizione di prospettive (perspective) avvengono attraverso l’implementazione di servizi OSGi. 7.1. Windows La transizione da finestra aperta a finestra chiusa e viceversa avviene attraverso l’implementazione di un servizio OSGi la cui interfaccia esposta dal bundle org.eclipse.fx.ui.workbench.renderers.base.services è org.eclipse.fx.ui.workbench.renderers.base.services.WindowTransitionService<Stage> I servizi OSGi possono essere definiti in modo dichiarativi in un file xml. L’IDE eclipse attraverso una procedura guidata permette la creazione di un file xml con le informazioni necessarie per la definizione del componente (servizio OSGi). Elementi essenziali del file sono il nome della classe dell’istanza del componente e l’interfaccia del servizio fornito. La procedura guidata inoltre aggiunge il riferimento di questo file al file MANIFEST.MF OSGI-INF/services/window-transition.xml. <?xml version="1.0" encoding="UTF-8"?> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/ v1.1.0" enabled="true" name="it.nelson.xbrl.client.app.WindowTransition"> <implementation class="it.nelson.xbrl.client.app.WindowTransition"/> <service> <provide interface="org.eclipse.fx.ui.workbench.renderers.base.services.WindowTransitionService"/ > </service> </scr:component> Nel MANIFEST.MF alla voce Service-Component c'è il riferimento ai file che descrivono i componenti, questi file in genere si creano in una cartella di nome OSGI-INF. META-INF/MANIFEST.MF. Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: My Sample App Bundle-SymbolicName: it.nelson.xbrl.client.app;singleton:=true Bundle-Version: 1.0.1.qualifier Require-Bundle: org.eclipse.fx.ui.workbench.fx, ... Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: javax.inject;version="1.0.0", ... Bundle-ActivationPolicy: lazy Service-Component: OSGI-INF/services/window-transition.xml Creazione del componente (servizio) OSGi attraverso la procedura guidata disponibile dall’ide eclipse. 152
  • 5. Windows Figura 7.3. Wizard per la creazione del servizio window transition Creazione della classe WindowTransition. Figura 7.4. Creazione della classe di implementazione del servizio Riferimento alla classe WindowTransition. 153
  • 6. Windows Figura 7.5. Riferimento alla classe del servizio Figura 7.6. Descrizione xml del servizio La descrizione del componente attraverso il file xml contiene tutte le informazioni del servizio, nome, classe e interfaccia del servizio 154
  • 7. Windows Figura 7.7. Sezione Services per selezionare l’interfaccia del servizio da implementare org.eclipse.fx.ui.workbench.renderers.base.services.WindowTransitionService come interfaccia del servizio Figura 7.8. Selezionata l’interfaccia WindowsTransitionService 155
  • 8. Windows Figura 7.9. file window-transition.xml Implementazione della classe WindowTransition: La transizione (animazione) avviene attraverso l’implementazione del metodo animate(@NonNull C window, @NonNull Runnable finished) del tipo AnimationDelegate<Node> definito come interfaccia annidata dell’interfaccia WindowTransitionService<Node> Figura 7.10. UML WindowTransition 156
  • 9. Windows Figura 7.11. La classe WindowTransition Figura 7.12. La classe StageFadeTransition 157
  • 10. Windows Figura 7.13. Warning Figura 7.14. Suppress warning 158
  • 11. Windows Figura 7.15. Verifica fade-transition apertura window Possibilità di abilitare o disabilitare il servizio dal file descrittore del servizio. Figura 7.16. Abilitare/Disabilitare il servizio window transition 159
  • 12. Windows Figura 7.17. Servizio window transition disabilitato Dunque in sintesi il file window-transition.xml definisce un componente di nome it.nelson.xbrl.client.app.WindowTransition che fornisce un servizio al OSGi-service-registry per l’interfaccia org.eclipse.fx.ui.workbench.renderers.base.services.WindowTransitionService. Servizio implementato dalla classe it.nelson.xbrl.client.app.WindowTransition (non è necessario che il nome della classe e il nome del componente coincidono) il cui sorgente è: /it.nelson.xbrl.client.app/src/it/nelson/xbrl/client/app/WindowTransition.java. package it.nelson.xbrl.client.app; import org.eclipse.e4.ui.model.application.ui.basic.MWindow; import org.eclipse.fx.ui.workbench.renderers.base.services.WindowTransitionService; import org.osgi.service.component.annotations.Component; import javafx.stage.Stage; import javafx.util.Duration; @SuppressWarnings("restriction") @Component public class WindowTransition implements WindowTransitionService<Stage> { @Override public AnimationDelegate<Stage> getShowDelegate( MWindow window) { return new AnimationDelegate<Stage>() { @Override public void animate(Stage window, Runnable finished) { window.setOpacity(0); window.show(); StageFadeTransition fade = new StageFadeTransition(window, 0, 1, Duration.millis(3000)); //fade transition di 3 secondi fade.setOnFinished( e -> finished.run()); fade.play(); } }; } @Override public AnimationDelegate<Stage> getHideDelegate( MWindow window) { return null; } } 160
  • 13. Dialogs /it.nelson.xbrl.client.app/src/it/nelson/xbrl/client/app/StageFadeTransition.java. package it.nelson.xbrl.client.app; import javafx.animation.Transition; import javafx.stage.Stage; import javafx.util.Duration; public class StageFadeTransition extends Transition { private final Stage stage; private final double start; private final double delta; public StageFadeTransition(Stage stage, double start, double end, Duration duration) { this.stage = stage; this.start = start; this.delta = end - start; setCycleDuration(duration); } @Override protected void interpolate(double frac) { double v = start + frac * delta; final double newOpacity = Math.max(0.0, Math.min(v, 1.0)); stage.setOpacity(newOpacity); } } 7.2. Dialogs Il sistema di dialogo è costruito attorno alla classe base org.eclipse.fx.ui.controls.dialog.Dialog con le classi derivate: 1. TitleAreaDialog (finestra di dialogo con un’area riservata in alto per visualizzare le informazioni) 2. MessageDialog (QUESTION, INFORMATION, WARNING, ERROR, CONFIRM, QUESTION_CANCEL) Le applicazioni eclipse RCP (E4) con javafx possono utilizzare le finestre di dialogo attraverso un nuovo servizio denominato org.eclipse.fx.ui.services.dialog.LightWeightDialogService così l’apertura di una finestra di dialogo può essere eseguita con: @Execute public void openDialog(LightWeightDialogService service) { MyDialog d = new MyDialog(); service.openDialog(d, ModalityScope.WINDOW); } 161
  • 14. Dialogs Figura 7.18. UML LightWeightDialogService Figura 7.19. UML Dialog La classe TestDialogHandler. package it.nelson.xbrl.client.app.handlers; import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.fx.ui.services.dialog.LightWeightDialogService; import org.eclipse.fx.ui.services.dialog.LightWeightDialogService.ModalityScope; public class TestDialogHandler { @Execute public void execute(LightWeightDialogService dialogService) { MyDialog myDialog = new MyDialog("frame title", "title", "message"); dialogService.openDialog(myDialog, ModalityScope.WINDOW); } } La classe myDialog. package it.nelson.xbrl.client.app.handlers; import org.eclipse.fx.ui.controls.dialog.TitleAreaDialog; import javafx.scene.control.Button; 162
  • 15. Dialogs import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; @SuppressWarnings("restriction") public class MyDialog extends TitleAreaDialog { public MyDialog(String frameTitle, String title, String message) { super(frameTitle, title, message); // nodo che riempie la client area Label lbtop = new Label("Client area border layout (top)"); Button btnr = new Button("Right"); Button btnl = new Button("Left"); Button btnc = new Button("Center"); Hyperlink link = new Hyperlink("Bottom"); BorderPane clientArea = new BorderPane(btnc, lbtop, btnr, link, btnl); // setClientArea(clientArea); addDefaultButtons(); // setMaxHeight(500); setPrefHeight(400); setPrefWidth(500); setId("test-dialog"); // id selector template css } } Css dialog. /* Css dialog */ .efx-dialog-title-image { -fx-image: url(icons/64/applications-system.png); } #open-project-dialog .efx-dialog-title-image { -fx-image: url(icons/64/prj_obj.png); } #open-project-dialog .efx-dialog-messageArea-area { -fx-background-color: rgb(192.0,192.0,192.0) ; } #test-dialog .efx-dialog-title-image { -fx-image: url(icons/64/application-x-java.png); } #test-dialog .efx-dialog-graphic-container { -fx-background-color: blue ; } #test-dialog .efx-dialog-messageArea-area { -fx-background-color: red ; } #test-dialog .efx-dialog-title { /* -fx-background-color: beige ; */ -fx-font-size: 16pt; 163
  • 16. Dialogs } #test-dialog .efx-dialog-title-message { -fx-font-size: 14pt; } #test-dialog .efx-dialog-title-font-icon { } Figura 7.20. Finestra MyDialog di tipo TitleAreaDialog Creazione di una finestra di dialogo di tipo TitleAreaDialog con una client area costituita da una lista di elementi. Figura 7.21. Menu, comando e gestore dell’apertura della finestra di esempio 164
  • 17. Dialogs Figura 7.22. Classe apertura finestra di dialogo Figura 7.23. Css della finestra di dialogo 165
  • 18. Dialogs Figura 7.24. Finestra di dialogo in esecuzione Mentre la classe TitleAreaDialog consente di creare facilmente una finestra di dialogo di tipo pop-up con uno spazio riservato per fornire feedback all’utente e creare un proprio layout, la classe MessageDialog consente all’utente di essere avvisato di qualcosa o confermare una domanda tipo yes/no/cancel. Tutte le finestre di dialogo (TitleAreaDialog e MessageDialog) create sono modali cioè blocca il thread corrente fino a quando l’interazione con l’utente non è stata completata. Esempio di finestra di conferma. package it.nelson.xbrl.client.app.lifecycle; import org.eclipse.e4.ui.model.application.ui.basic.MWindow; import org.eclipse.fx.ui.dialogs.MessageDialog; import org.eclipse.fx.ui.dialogs.MessageDialog.ConfirmResult; import org.eclipse.fx.ui.workbench.renderers.base.widget.WWindow; import org.eclipse.fx.ui.workbench.services.lifecycle.annotation.PreClose; import org.eclipse.fx.ui.workbench.services.lifecycle.annotation.PreShow; import javafx.stage.Stage; public class LifeCycle { @PreShow public void execute() { System.err.println("PreShow"); } @PreClose public boolean ph(MWindow win) { System.err.println("PreClose"); 166
  • 19. Dialogs if (MessageDialog.openConfirmDialog((Stage) ((WWindow) win.getWidget()).getWidget(), "Messaggio di conferma", "Conferma chiusura scheda?") == ConfirmResult.OK) return true; else return false; } } Figura 7.25. Esempio di finestra di conferma Esempio di finestra di informazione. ... @FXML void actSave(ActionEvent event) { bookService.addBook(DATASOURCE.get(idListView.getSelectionModel().getSelectedIndex())); MessageDialog.openInformationDialog(stage, "Conferma", "Salvato libro con id= " + DATASOURCE.get(idListView.getSelectionModel().getSelectedIndex()).getId()); } ... 167
  • 20. Dialogs Figura 7.26. Esempio di finestra di informazione Esempio di finestra di errore. ... try { bookService.init(); } catch (Throwable e) { System.err.println("Impossibile stabilire connessione con il DB"); MessageDialog.openErrorDialog(stage, "ERRORE DI CONNESSIONE", "Non posso creare EntityManagerFactory: " + e.getMessage()); throw new ExceptionInInitializerError(e); } ... 168
  • 21. Dialogs Figura 7.27. Esempio di finestra di errore Mentre il servizio di dialogo consente di aprire una finestra di dialogo e controllare la sua modalità, c'è un secondo servizio che è in grado di controllare come viene mostrata / nascosta una finestra di dialogo. Di default la finestra di dialogo è semplicemente mostrata e nascosta ma si possono aggiungere anche delle animazioni come mostrato di seguito La finestra di dialogo può essere aperta in modo animato attraverso l’implementazione di un servizio OSGi la cui interfaccia esposta dal bundle org.eclipse.fx.ui.workbench.renderers.fx.services è org.eclipse.fx.ui.workbench.renderers.fx.services.LightweightDialogTransitionService Il package package org.eclipse.fx.ui.workbench.renderers.fx.services fornisce delle classi di transizioni delle finestre di dialogo con l’implementazioni di transizioni (animazioni) predefinite: 1. FadeDialogTransitionService: classe astratta da ereditare per implementare una transizione della finestra di dialogo per dissolvenza, la classe derivata può riscrivere i metodi ereditati per variare le proprietà dell’animazione: • protected void configureFadeIn(FadeTransition transition) • protected void configureFadeOut(FadeTransition transition) 2. FlyInTransitionService: classe concreta da ereditare per implementare transizione per variazione della posizione verticale (apertura dall’alto verso il basso chiusura dal basso verso l’alto) 169
  • 22. Dialogs Figura 7.28. UML DialogTransitionService Esempio di implementazione del servizio di trasparenza finestre di dialogo package it.nelson.xbrl.client.app; import org.eclipse.fx.ui.workbench.renderers.fx.services.FadeDialogTranstionService; import org.eclipse.fx.ui.workbench.renderers.fx.services.LightweightDialogTransitionService; import org.osgi.service.component.annotations.Component; import javafx.animation.FadeTransition; import javafx.animation.Interpolator; import javafx.util.Duration; @Component(service = LightweightDialogTransitionService.class) public class DialogTransition extends FadeDialogTranstionService { @Override protected void configureFadeIn(FadeTransition transition) { super.configureFadeIn(transition); transition.setInterpolator(Interpolator.EASE_IN); transition.setDuration(Duration.millis(600)); } @Override protected void configureFadeOut(FadeTransition transition) { super.configureFadeOut(transition); transition.setInterpolator(Interpolator.EASE_OUT); transition.setDuration(Duration.millis(600)); } } 170
  • 23. Dialogs Figura 7.29. Definizione servizio transizione della finestra di dialogo Figura 7.30. Nome e riferimento della classe del servizio 171
  • 24. Dialogs Figura 7.31. Ricerca dell’interfaccia che fornisce il servizio Figura 7.32. Interfaccia che fornisce il servizio 172
  • 25. Dialogs Figura 7.33. Classe che implementa il servizio di transizione per dissolvenza FadeDialogTranstionService è la classe che implementa la transizione per dissolvenza, la classe derivata può riscrivere i metodi ereditati: • protected void configureFadeIn(FadeTransition transition) • protected void configureFadeOut(FadeTransition transition) Figura 7.34. Riscrittura metodi ereditati 173
  • 26. Dialogs Figura 7.35. Fade transition della finestra di dialogo in esecuzione Di seguito l’altra animazione predefinita della finestra di dialogo implementata attraverso la classe FlyInTransitionService package it.nelson.xbrl.client.app; import org.eclipse.fx.ui.workbench.renderers.fx.services.FlyInTransitionService; import org.eclipse.fx.ui.workbench.renderers.fx.services.LightweightDialogTransitionService; import org.osgi.service.component.annotations.Component; @Component(property = { "service.ranking:Integer=-1" }) public class FlyinTransitionServiceImpl extends FlyInTransitionService implements LightweightDialogTransitionService { } 174
  • 27. Dialogs Figura 7.36. Nome e riferimento della classe del servizio Figura 7.37. La classe che implementa il servizio 175
  • 28. Dialogs Figura 7.38. Proprietà ranking del servizio Figura 7.39. Interfaccia che fornisce il servizio 176
  • 29. Dialogs Figura 7.40. Finestra di dialogo con animazione predefinita dalla classe FlyInTransitionService Implementazione di una animazione non predefinita. Figura 7.41. La classe che implementa il servizio Figura 7.42. Metodi da implementare segnati dall’interfaccia 177
  • 30. Dialogs Figura 7.43. Metodi da implementare Figura 7.44. Implementazione dei metodi 178
  • 31. Dialogs Figura 7.45. Nuovo riferimento di classe nel servizio di transizione della finestra di dialogo Figura 7.46. Servizio implementato dalla classe MyAnimTransitionServiceImpl Utilizzando le api di javaFX: fadeTransition e rotateTransition MyAnimTransitionServiceImpl.java. package it.nelson.xbrl.client.app; import org.eclipse.e4.ui.model.application.ui.MUIElement; import org.eclipse.fx.ui.workbench.renderers.fx.services.LightweightDialogTransitionService; import org.osgi.service.component.annotations.Component; import javafx.animation.FadeTransition; import javafx.animation.Interpolator; import javafx.animation.ParallelTransition; import javafx.animation.RotateTransition; import javafx.animation.TranslateTransition; import javafx.scene.Node; import javafx.scene.layout.Pane; import javafx.util.Duration; @Component(property = { "service.ranking:Integer=-1" }) public class MyAnimTransitionServiceImpl implements LightweightDialogTransitionService { private boolean fadeGrayArea; @Override 179
  • 32. Dialogs public void showDialog(MUIElement container, Pane containerNode, Pane dialogOverlayContainer, Node grayArea, Node dialog, Runnable finished) { FadeTransition fd = new FadeTransition(Duration.millis(4000), dialogOverlayContainer); fd.setFromValue(0.0); fd.setToValue(1.0); TranslateTransition t = new TranslateTransition(Duration.millis(4000), dialog); t.setFromY(-1 * (dialog.getLayoutY() + dialog.prefHeight(-1))); t.setFromX(-1 * (dialog.getLayoutX() + dialog.prefWidth(-1))); t.setToX(0); t.setToY(0); t.setInterpolator(Interpolator.EASE_OUT); if (finished != null) { t.setOnFinished(e -> { finished.run(); }); } ParallelTransition p = new ParallelTransition(t); if (this.fadeGrayArea) { p.getChildren().add(fd); } p.play(); } @Override public void hideDialog(MUIElement container, Pane containerNode, Pane dialogOverlayContainer, Node grayArea, Node dialog, Runnable finished) { RotateTransition r = new RotateTransition(Duration.millis(2000), dialog); r.setByAngle(180f); r.setCycleCount(4); r.setAutoReverse(true); if (finished != null) { r.setOnFinished(e -> { finished.run(); }); } r.play(); } } otteniamo una animazione di tipo rotazione e dissolvenza 180
  • 33. Dialogs Figura 7.47. Animazione in esecuzione Utilizzando le api di javaFX: pathTransition e CubicCurveTo otteniamo una animazione più complessa @Override public void hideDialog(MUIElement container, Pane containerNode, Pane dialogOverlayContainer, Node grayArea, Node dialog, Runnable finished) { Path path = new Path(); path.getElements().add(new MoveTo(-30, -30)); path.getElements().add(new CubicCurveTo(400, 0, 400, 100, 200, 100)); path.getElements().add(new CubicCurveTo(0, 100, 0, 240, 400, 240)); PathTransition pathTransition = new PathTransition(); pathTransition.setDuration(Duration.millis(3000)); pathTransition.setPath(path); pathTransition.setNode(dialog); pathTransition.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT); pathTransition.setCycleCount(2); pathTransition.setAutoReverse(true); if (finished != null) { pathTransition.setOnFinished(e -> { finished.run(); }); } pathTransition.play(); } 181
  • 34. Perspective Figura 7.48. Animazione in esecuzione 7.3. Perspective La transizione delle prospettive (perspective) avviene attraverso l’implementazione di un servizio OSGi la cui interfaccia esposta dal bundle org.eclipse.fx.ui.workbench.renderers.base.services è org.eclipse.fx.ui.workbench.renderers.base.services.PerspectiveTransitionService<BorderPane,Node> Il package org.eclipse.fx.ui.animation.pagetransition.animation fornisce delle classi di transizioni con l’implementazioni di transizioni (animazioni) predefinite Figura 7.49. UML org.eclipse.fx.ui.animation.pagetransition Quindi per realizzare ad esempio una animazione di una prospettiva che si apre con effetto zoom occorre definire il servizio OSGi descritto nel file perspective-animation.xml perspective-animation.xml. <?xml version="1.0" encoding="UTF-8"?> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" enabled="true" name="it.nelson.xbrl.client.app.PerspectiveAnimation"> <implementation class="it.nelson.xbrl.client.app.PerspectiveAnimation"/> <service> <provide interface="org.eclipse.fx.ui.workbench.renderers.base.services.PerspectiveTransitionService"/ > </service> 182
  • 35. Perspective </scr:component> e la classe it.nelson.xbrl.client.app.PerspectiveAnimation che implementa il servizio: PerspectiveAnimation.java. import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective; import org.eclipse.fx.ui.animation.pagetransition.animation.ZoomSlideAnimation; import org.eclipse.fx.ui.workbench.renderers.base.services.PerspectiveTransitionService; import org.osgi.service.component.annotations.Component; import javafx.scene.Node; import javafx.scene.layout.BorderPane; @SuppressWarnings("restriction") @Component public class PerspectiveAnimation implements PerspectiveTransitionService<BorderPane, Node> { @Override public AnimationDelegate<BorderPane, Node> getDelegate(MPerspective fromPerspective, MPerspective toPerspective) { return new AnimationDelegate<BorderPane, Node>() { @Override public void animate(BorderPane container, Node control, Runnable finished) { ZoomSlideAnimation animation = new ZoomSlideAnimation(); animation.animate(container, control, finished); } }; } } In figura un esempio di implementazione per la transizione di perspective mediante l’animazione predefinita PageChangeAnimation. Figura 7.50. Animazione transizione prospettive Definizione del servizio OSGi mediante il wizard component definition in plug-in development di eclipse 183
  • 36. Perspective Figura 7.51. Servizio perspective animation Figura 7.52. Definizione del fornitore del servizio 184
  • 37. Perspective Figura 7.53. Errore dopo esecuzione Figura 7.54. Errore causato da una dipendenza non corretta (da rimuovere) 185
  • 38. Perspective Figura 7.55. Segnalzione nel codice dopo rimozione dipendenza Figura 7.56. Package giusto da importare 186
  • 39. Perspective Figura 7.57. Codice dopo importazione package Figura 7.58. Verifica mediante esecuzione Realizzazione di una animazione di una prospettiva che si apre con effetto non predefinito ma costruito attraverso una classe che estende la superclasse CenterSwitchAnimation e l’implementazione dei metodi ereditati attraverso le api javaFX 187
  • 40. Perspective Figura 7.59. Descrizione del servizio di animazione nel cambio prospettiva Figura 7.60. Interfaccia che fornisce il servizio 188
  • 41. Perspective Figura 7.61. Descrizione del servizio in xml Figura 7.62. Classe delegata che implementa l’interfaccia del servizio Costruzione della classe MyAnimRotate che estende la superclasse CenterSwitchAnimation 189
  • 42. Perspective Figura 7.63. Creazione della classe MyAnimRotate Figura 7.64. Sorgente della classe MyAnimRotate Implementazione dei metodi ereditati dalla superclasse CenterSwitchAnimation mediante le classi javaFX RotateTransition e FadeTransition 190
  • 43. Perspective Figura 7.65. Implementazione dei metodi ereditati dalla superclasse CenterSwitchAnimation Figura 7.66. Animazione cambio prospettiva in esecuzione Animazione più complessa mediante l’implementazione dei metodi ereditati dalla superclasse CenterSwitchAnimation con le classi javaFX PathTransition e ScaleTransition 191
  • 45. Perspective Figura 7.68. Classe che implementa il servizio Figura 7.69. Animazione in esecuzione 193
  • 46. 194