Transparents du cours.

Transcription

Transparents du cours.
Interfaces graphiques - JavaFX
responsable : Wieslaw Zielonka
[email protected]
http://liafa.univ-paris-diderot.fr/∼zielonka
February 24, 2016
propriétés −→ listeners
évènements −→ handlers
Propriétés (beans de javafx)
Une propriété d’un objet (dans le sens de javafx) est une variable
privée d’instance de l’objet qui satisfait les conditions suivantes :
I
le type de cette variable est un des types défini dans le
package javafx.beans.property :
BooleanProperty, DoubleProperty, IntegerProperty,
ObjectProperty, StringProperty etc.
Évidemment BooleanProperty permet de stocker une valeur
booléenne, DoubleProperty une valeur double etc.
Définir une propriété
I
pour chaque propriété la classe définit trois méthodes.
Supposons par exemple que la classe possède une variable
d’instance
private DoubleProperty hauteurMaison =
new S i m p l e D o u b l e P r o p e r t y ( ) ;
Dans ce cas la classe doit définir les méthodes :
p u b l i c f i n a l double
getHauteurMaison (){ return hauteurMaison . get ( ) ; }
public f i n a l void
s e t H a u t e u r M a i s o n ( double v ) { h a u t e u r M a i s o n . s e t ( v ) ; }
public DoubleProperty
hauteurMaisonProperty (){ return hauteurMaison ;}
Notez la correspondance entre le nom de la propriété et les noms
des méthodes.
Autre exemple
p u b l i c c l a s s Model {
// L e s d o n n e e s s o n t c o n s t i t u e e s d ’ un s e u l e n t i e r .
private IntegerProperty entier ;
Model ( i n t v a l ) { e n t i e r =
new S i m p l e I n t e g e r P r o p e r t y ( v a l ) ; }
Model ( ) { t h i s ( 0 ) ; }
public f i n a l int getEntier (){
return e n t i e r . get ( ) ;
}
public f i n a l IntegerProperty entierProperty (){
return e n t i e r ;
}
p u b l i c f i n a l void s e t E n t i e r ( i n t v a l ){
entier . set ( val );
}
}
Définir ChangeListeners
Pour chaque propriété nous pouvons définir un listener
ChangeListener qui sera activé quand la valeur de la propriété
change. Par exemple un listener pour la propriété du modèle de la
page précédente :
C h a n g e L i s t e n e r <Number> m o d e l L i s t e n e r =
new C h a n g e L i s t e n e r <Number >() {
@Override
p u b l i c v o i d c h a ng ed (
O b s e r v a b l e V a l u e <? e x t e n d s Number> o b s e r v a b l e ,
Number o l d v a l ,
Number n e w v a l ) {
// m e t t r e a j o u r s l e s v i e w s quand l a p r o p r i e t e
// du modele c h a n g e
f o r ( UpdatableView view : views ){
v i e w . u p d a t e ( model . g e t E n t i e r ( ) ) ;
// v i e w . u p d a t e ( n e w v a l . i n t V a l u e ( ) ) ;
}
}
};
Enregistrer ChangeListener pour la propriété du modèle
model . e n t i e r P r o p e r t y ( ) . a d d L i s t e n e r ( m o d e l L i s t e n e r ) ;
Notez que ChangeListener était paramétré par un type qui
dépend de type de la propriété.
Propriété de contrôles
Les contrôles sont des beans de javafx, par exemple :
CheckBox
ChoiceBox
Slider
etc
BooleanProperty selected
ObjectProperty<T> value
DoubleProperty value
Ces trois contrôles possèdent aussi d’autres propriétés et tous les
contrôles possèdent de propriétés auxquelles on peut attacher
ChangeListeners.
ChoiceBoxView avec un ChangeListener
p u b l i c c l a s s Ch oi ceBoxView e x t e n d s ChoiceBox<I n t e g e r > {
p r i v a t e Model model ;
// i n t L i s t s e r t a s t o c k e r l e s d o n n e e s de C h o i c e B o x
O b s e r v a b l e L i s t <I n t e g e r > i n t L i s t ;
{
I n t e g e r [ ] i n t a = new I n t e g e r [ 1 6 ] ;
int k = 1;
f o r ( i n t i = 0 ; i < i n t a . l e n g t h ; i ++) {
i n t a [ i ] = new I n t e g e r ( k ) ;
k <<= 1 ;
}
i n t L i s t = FXCollections . observableArrayList ( inta );
}
ChoiceBoxView avec un ChangeListener (suite)
// c o n s t r u c t e u r
p u b l i c Ch oi ceB oxV iew ( Model model ) {
t h i s . model = model ;
setItems ( intList );
// a t t a c h e r un C h a n g e L i s t e n e r
v a l u e P r o p e r t y ( ) . a d d L i s t e n e r ( new C h a n g e L i s t e n e r <O b j e c t >() {
@Override
p u b l i c v o i d c h a n g ed ( O b s e r v a b l e V a l u e <? e x t e n d s O b j e c t > ov ,
Object o l d v a l , Object new val ) {
model . s e t E n t i e r ( ( ( I n t e g e r ) n e w v a l ) . i n t V a l u e ( ) ) ;
}
});
Le modèle de ChoiceBox possède aussi la propriété
selectedIndex, donc une autre possibilité consiste à attacher un
ChangeListener au modèle (voir le tutorial sur ChoiceBox) :
getSelectionModel ( ) . selectedIndexProperty ()
. a d d L i s t e n e r ( new C h a n g e L i s t e n e r <Number >() {
@Override
p u b l i c v o i d c h ang ed ( O b s e r v a b l e V a l u e <? e x t e n d s Number> ov ,
Number o l d v a l , Number n e w v a l ) {
model . s e t E n t i e r ( i n t L i s t
. get ( new val . intValue ( ) ) . intValue ( ) ) ;
}
});
Gestion d’evenements
Évènement correspond souvent à une action de l’utilisateur : click
de souris, taper sur le clavier, un geste sur l’écran tactile.
Un évènement est une instance de javafx.event.Event.
Les types évènements sont regroupés dans de classes d’évènements,
dans chaque classe il y a plusieurs types d’évènements.
Exemple : la classe KeyEvent contient les types : KEY_PRESSED,
KEY_RELEASED, KEY_TYPED.
Hiérarchie (partielle) d’évènements
KeyEvent.KEY_PRESSED
KeyEvent.KEY_RELEASED
KeyEvent.KEY_TYPED
| KeyEvent.ANY
|
|InputEvent.ANY| MouseEvent.ANY MouseEvent.MOUSE_PRESSED
|
MouseEvent.MOUSE_RELEASED
Event.ANY -|
MouseEvent.MOUSE_DRAGGED
|
[ActionEvent.ACTION
|
|WindowEvent.ANY----|WindowEvent.WINDOW_SHOWING
|WindowEvent.WINDOW_SHOWN
Propagation d’évènements
Click sur un rectangle :
Stage → Scene → BorderPane → Pane → Rectangle
L’évènement se propage d’abord depuis Stage jusqu’au
Rectangle (Event Capturing Phase) et ensuite dans le sens
inverse depuis Rectangle jusqu’à Stage (Event Bubbling Phase).
A chaque noeud (Node) nous pouvons associé des EventFilters
et des EventHandlers appelés pour traiter l’évènement.
Quelle est la différence entre un EventFilter et un
EventHandler ?
Un EventFilter est exécuté pendant Event Capturing Phase.
Un EventHandler est exécuté pendant Event Bubbling Phase.
Un noeud peut enregistrer plusieurs filtres, l’ordre d’exécution est
basé sur la hiérarchie d’évènement, d’abord les filtres plus
spécifiques ensuite plus généraux (MouseEvent.MOUSE_PRESSED
avant MouseEvent.ANY).
Un noeud peut enregistrer plusieurs handlers, l’ordre d’exécution
est basé sur la hiérarchie d’évènement, d’abord les filtres plus
spécifiques ensuite plus généraux (KeyEvent.KEY_TAPED avant
KeyEvent.ANY).
Arrêter la propagation d’un évènement
La propagation d’un évènement peut-être arrêtée en exécutant la
méthode
event.consume()
Un évènement consumé par un EventFilter ne passe pas dans la
classe enfant, un évènement consumé par un EventHandler ne
passe pas dans la classe parent.
Si un noeud possède plusieurs EventFilters qui correspondent à un
évènement alors même si cet évènement est consumé par un
EventFilter tous les filtres seront quand même exécutés.
Même chose pour EventHandlers.
Construire et enregistrer EventFilters
node . a d d E v e n t F i l t e r ( MouseEvent . MOUSE CLICKED ,
new E v e n t H a n d l e r <MouseEvent >(){
p u b l i c v o i d h a n d l e ( MouseEvent e v e n t ) {
// i m p l e m e n t e r l e f i l t r e
// e v e n t . consume ( ) ;
}
});
Noter que addEventFilter a deux paramètres :
I
un EventType et
I
un EventHandler.
Construire et enregistrer EventHandlers
node . a d d E v e n t H a d l e r ( KeyEvent . KEY TAPED ,
new E v e n t H a n d l e r <KeyEvent >(){
p u b l i c v o i d h a n d l e ( KeyEvent e v e n t ) {
// i m p l e m e n t e r l e f i l t r e
// e v e n t . consume ( ) ;
}
});
Noter que addEventHandler a les mêmes paramètres que
addEventFilter.
Enregistrer un seul EventHandler
La classe Node (donc toutes les classes dérivées de Node) fournit
des méthodes setOnNomHandler de commodité qui permettent
d’enregistrer un seul handler, par exemple
node . s e t O n M o u s e P r e s s e d ( new E v e n t H a n d l e r <MouseEvent >() {
@Override
p u b l i c v o i d h a n d l e ( f i n a l MouseEvent e v e n t ) {
}
});
Ces méthodes correspondent aux propriétés de la classe Node (par exemple
MousePressedProperty, MouseDraggedProperty etc.). L’avantage de ces
méthodes par rapport à ma méthode addEventHandler() c’est la simplicité,
un seul argument à la place de deux arguments.
Si vous voulez supprimer un EventHandler installé par une de méthodes setOn
il suffit de passer l’argument null.
La liste d’enfant d’un noeud
Si on a un noeud (par exemple Pane) de type Parent on lui ajoute
un enfant par
pane . g e t C h i l d r e n ( ) . add ( e n f a n t ) ;
Chaque parent possède une liste des enfants et getChildren()
retourne cette liste. La méthode add() ajoute enfant à la fin de
la liste.
Quand le parent est rendu sur l’écran les enfants sont rendus dans
l’ordre de leur apparition sur la liste des enfants, le premier celui en
tête de la liste jusqu’au dernier, celui à la fin de la liste.