7/23/2019 Java FX Partie6
1/50
Cours IHM
-
1JavaFX
Jacques BAPST
6
-
Architecture MVC
Gestion des vnements
7/23/2019 Java FX Partie6
2/50
Architecture
MVC
Structure d'une application
IHM-1 FX06 Jacques BAPST 2
7/23/2019 Java FX Partie6
3/50
Architecture
MVC
[1]
Il existe diffrentes manires de structurer le code des applications
interactives (celles qui comportent une interface utilisateur).
Une des architectures, communment utilise, et qui comporte denombreuses variantes, est connue sous l'acronyme MVC qui signifieModel - View - Controller.
Dans cette architecture on divise le code des applications en entitsdistinctes (modles, vues et contrleurs) qui communiquent entre-elles au moyen de divers mcanismes (invocation de mthodes,gnration et rception d'vnements, etc.).
Cette architecture (ou modle de conception, design pattern) a t
introduite avec le langage Smalltalk-80 dans le but de simplifier ledveloppement ainsi que la maintenance des applications, enrpartissant et en dcouplant les activits dans diffrents sous-systmes (plus ou moins) indpendants.
IHM-1 FX06 Jacques BAPST 3
7/23/2019 Java FX Partie6
4/50
7/23/2019 Java FX Partie6
5/50
Interactions
MVC
[1]
Un exemple de communication entre les lments (MVC synchrone).
IHM-1 FX06 Jacques BAPST 5
Flux de donnes
vnements
Model View
Controller
La vue peut consulter
les donnes du modle.
La vue dtermine quels
vnements sont passs
au contrleur.
Le contrleur peut demander
la mise jour des lments
affichs.
Le contrleur peut
consulter et mettre
jour le modle en fonction
des vnements.
7/23/2019 Java FX Partie6
6/50
7/23/2019 Java FX Partie6
7/50
7/23/2019 Java FX Partie6
8/50
MVC Vue
La vue (View) est charge de la reprsentation visuelle des
informations en faisant appel des crans, des fentres, descomposants, des conteneurs (layout), des botes de dialogue, etc.
Plusieurs vues diffrentes peuvent tre bases sur le mme modle(plusieurs reprsentations possibles d'un mme jeu de donnes).
La vue intercepte certaines actions de l'utilisateur et les transmet aucontrleur pour qu'il les traite (souris, clavier, gestes, ).
La mise jour de la vue peut tre dclenche par un contrleur oupar un vnement signalant un changement intervenu dans lesdonnes du modle par exemple (mode asynchrone).
La reprsentation visuelle des informations affiches peut dpendredu Look-and-Feeladopt (ou impos) et peut varier d'uneplateforme l'autre. L'utilisateur peut parfois modifier lui mme lethme de prsentation des informations.
IHM-1 FX06 Jacques BAPST 8
7/23/2019 Java FX Partie6
9/50
MVC Contrleur
Le contrleur (Controller) est charg de ragir aux diffrentes
actions de l'utilisateur ou d'autres vnements qui peuventsurvenir.
Le contrleur dfinit le comportement de l'application et sa logique(comment elle ragit aux sollicitations, business logic).
Dans les applications simples, le contrleur gre la synchronisationentre la vue et le modle (rle de chef d'orchestre).
Le contrleur est inform des vnements qui doivent tre traits etsait d'o ils proviennent.
La plupart des actions tant interceptes (ou en lien) avec la vue, ilexiste un couplage assez fort entre la vue et le contrleur.
Le contrleur communique gnralement avec le modle et avec lavue. C'est le sens des transferts et le mode de communication quicaractrisent diffrentes variantes de l'architecture MVC.
IHM-1 FX06 Jacques BAPST 9
7/23/2019 Java FX Partie6
10/50
Structure d'une application [1]
Une applicationJavaFXqui respecte l'architecture MVC comprendra
gnralement diffrentes classes et ressources : Le modle sera frquemment reprsent par une ou plusieurs classes
qui implmentent gnralement une interface permettant de s'abstrairedes techniques de stockage des donnes.
Les vues seront soit codes enJava ou dclares en FXML. Des feuilles
de styles CSS pourront galement tre dfinies pour dcrire le rendu. Les contrleurs pourront prendre diffrentes formes :
Ils peuvent tre reprsents par des classes qui traitent chacune unvnement particulier ou qui traitent plusieurs vnements en relation(menu ou groupe de boutons par exemple)
Si le code est trs court, ils peuvent parfois tre inclus dans les vues, sous
forme de classes locales anonymes ou d'expressions lambda. La classe principale (celle qui comprend la mthode main()) peut faire
l'objet d'une classe spare ou tre intgre la classe de la fentreprincipale (vue principale).
D'autres classes utilitaires peuvent venir complter l'application.
IHM-1 FX06 Jacques BAPST 10
7/23/2019 Java FX Partie6
11/50
7/23/2019 Java FX Partie6
12/50
Gestion des vnements
IHM-1 FX06 Jacques BAPST 12
7/23/2019 Java FX Partie6
13/50
Programmation vnementielle [1]
La programmation des applications avec interfaces graphiques est
gnralement base sur un paradigme nomm programmationvnementielle (Event Programming).
Dans la programmation imprative (squence d'instructions), c'estle programme qui dirige les oprations (par exemple, il demande l'utilisateur d'entrer des valeurs, calcule et affiche un rsultat, etc.).
Avec la programmation vnementielle, ce sont les vnements(gnralement dclenchs par l'utilisateur, mais aussi par le systme) quipilotent l'application. Ce mode non directif convient bien la gestiondes interfaces graphiques o l'utilisateur une grande libertd'action (l'interface est au service de l'utilisateur et non l'inverse).
La programmation vnementielle ncessite qu'un processus (entche de fond) surveille constamment les actions de l'utilisateursusceptibles de dclencher des vnements qui pourront treensuite traits (ou non) par l'application (contrleurs).
IHM-1 FX06 Jacques BAPST 13
7/23/2019 Java FX Partie6
14/50
Programmation vnementielle [2]
En programmation squentielle, une interface utilisateur (en lignes
de commandes) pourrait tre code selon le pseudo-code suivant quiillustre le principe.
IHM-1 FX06 Jacques BAPST 14
SequentialProg {
Initialize();
Loop {
cmd = readCommand();
Switch (cmd) {
Case: command1
process_cmd1();
Case: command2
process_cmd2();
Case: command3
process_cmd3();Case: . . .
. . .
}
}
}
Une boucle sans fin rpte le cycle
suivant :- Demande l'utilisateur de saisirune commande (prompt)
- Attend que la prochainecommande soit entre auclavier (+dcodage)
- Selon la commande entre, ducode spcifique est excut.
Lorsque le traitement est termin,le cycle recommence (on attend laprochaine commande).
7/23/2019 Java FX Partie6
15/50
Programmation vnementielle [3]
En programmation vnementielle, on prpare les actions (code)
excuter en les associant aux vnements que l'on souhaite traiter(enregistrement des callback) et on attend que le processus desurveillance nous avertisse en excutant le code prvu.
IHM-1 FX06 Jacques BAPST 15
EventProg {
Initialize();
CreateGUI();RegisterCallback();
StartEventLoop(); // Thread
________________________________________________________________________________
Callback1() // Button clicked
code1;
Callback2() // Key pressed
code2;
Callback3() // Window resized
code3
. . . // Pinch gesture
. . .
}
Aprs initialisation, on cre l'interface
graphique puis on associe du code chaque vnement que l'on souhaitetraiter (RegisterCallback).
Lorsque les vnements enregistrsse produisent, le code associ estautomatiquement excut par leprocessus de surveillance qui tourneen tche de fond Event Thread.
EventLoopT
hread
7/23/2019 Java FX Partie6
16/50
vnement [1]
Un vnement (event) constitue une notification qui signale que
quelque chose s'est pass (un fait, un acte digne d'intrt). Un vnement peut tre provoqu par :
Une action de l'utilisateur Un clic avec la souris La pression sur une touche du clavier Le dplacement d'une fentre Un geste sur un cran tactile . . .
Un changement provoqu par le systme Une valeur a chang (proprit)
Un timerest arriv chance Un processus a termin un calcul Une information est arrive par le rseau . . .
IHM-1 FX06 Jacques BAPST 16
7/23/2019 Java FX Partie6
17/50
7/23/2019 Java FX Partie6
18/50
Types d'vnements
Chaque vnement est d'un certain type (objet de type EventType).
Chaque type d'vnement possde un nom (getName()) et un typeparent (getSuperType()).
Les types d'vnement forment donc une hirarchie. Par exemple si on presse une touche le nom de l'vnement est
KEY_PRESSED et le type parent est KeyEvent.ANY. A la racine, on a
Event.ANY
(=EventType.ROOT)
IHM-1 FX06 Jacques BAPST 18
La figure reprsente une partieseulement de la hirarchie destypes d'vnements.
7/23/2019 Java FX Partie6
19/50
7/23/2019 Java FX Partie6
20/50
Gestion des vnement [2]
Un exemple d'application avec son graphe de scne.
Si l'utilisateur clique sur le bouton Insert, un vnement de typeAction va tre dclench et va se propager le long du chemincorrespondant la chane de traitement (Event Dispatch Chain).
IHM-1 FX06 Jacques BAPST 20
Stage
Scene
BorderPane
HBoxLabel
ButtonInsert
ButtonDelete
ButtonQuit
TextArea
7/23/2019 Java FX Partie6
21/50
7/23/2019 Java FX Partie6
22/50
Gestion des vnement [4]
L'vnement remonte ensuite depuis la cible jusqu' la racine et les
gestionnaires d'vnements (Event Listener) ventuellementenregistrs sont excuts (dans l'ordre de passage).
IHM-1 FX06 Jacques BAPST 22
Stage
Scene
BorderPane
HBoxLabel
ButtonInsert
ButtonDelete
ButtonQuit
TextArea
Event Bubbling Phase
7/23/2019 Java FX Partie6
23/50
Gestion des vnements [5]
Pour grer un vnement (excuter des instructions), il faut crer un
rcepteur d'vnement (Event Listener), appel aussi couteurd'vnement, et l'enregistrer sur les nuds du graphe de scne ol'on souhaite intercepter l'vnement et effectuer un traitement.
Un rcepteur d'vnement peut tre enregistr comme filtre oucomme gestionnaire d'vnement. La diffrence principale entre
les deux rside dans le moment o le code est excut : Les filtres (filters) sont excuts dans la phase descendante de la chane
de traitement des vnements (avant les gestionnaires)
Les gestionnaires (handlers) sont excuts dans la phase montante de lachane de traitement des vnements (aprs les filtres)
Les filtres, comme les gestionnaires d'vnements, sont des objetsqui doivent implmenter l'interface fonctionnelle (gnrique)EventHandler qui impose l'unique mthodehandle(T event) qui se charge de traiter l'vnement.
IHM-1 FX06 Jacques BAPST 23
7/23/2019 Java FX Partie6
24/50
Gestion des vnements [6]
Pour enregistrer un rcepteur d'vnement sur un nud du graphe
de scne, on peut :
Utiliser la mthode addEventFilter() que possdent tous les nuds(les sous-classes de Node) et qui permet d'enregistrer un filtre
Utiliser la mthode addEventHandler() que possdent tous les nuds
(les sous-classes de Node) et qui permet d'enregistrer un gestionnaired'vnement
Utiliser une des mthodes utilitaires (convenience methods) dontdisposent certains composants et qui permettent d'enregistrer ungestionnaire d'vnement en tant que proprit du composant.
La plupart des composants disposent de mthodes nommes selon leschma setOnEventType(EventHandler), par exemple :
setOnAction(Handler)
setOnKeyTyped(Handler)
IHM-1 FX06 Jacques BAPST 24
7/23/2019 Java FX Partie6
25/50
7/23/2019 Java FX Partie6
26/50
Gestion des vnements [8]
Si un nud du graphe de scne possde plusieurs rcepteurs
d'vnements enregistrs, l'ordre d'activation de ces rcepteurssera bas sur la hirarchie des types d'vnement :
Un rcepteur pour un type spcifique sera toujours excut avant unrcepteur pour un type plus gnrique
Par exemple un filtre enregistr pour MouseEvent.MOUSE_PRESSED sera
excut avant un filtre pour MouseEvent.ANY qui sera excut avant unfiltre pour InputEvent.ANY
L'ordre d'excution desrcepteurs pour des typesde mme niveau n'estpas dfini
La consommation d'unvnement n'interromptpas le traitement des autresrcepteurs enregistrs sur lemme nud
IHM-1 FX06 Jacques BAPST 26
7/23/2019 Java FX Partie6
27/50
Event Handling [1]
IHM-1 FX05 Jacques BAPST 27
privateBorderPane root = newBorderPane();
privateHBox btnPanel = newHBox(10);
privateLabel lblTitle = newLabel("Event Handling");
privateTextArea txaMsg = newTextArea();
privateButton btnInsert= newButton("Insert");
privateButton btnDelete= newButton("Delete");
privateButton btnQuit = newButton("Quit");
primaryStage.setTitle("Event Handling");
root.setPadding(newInsets(10));
//--- Title
lblTitle.setFont(Font.font("System", FontWeight.BOLD, 20));
lblTitle.setTextFill(Color.DARKGREEN);
BorderPane.setAlignment(lblTitle, Pos.CENTER);
BorderPane.setMargin(lblTitle, newInsets(0, 0, 10, 0));
root.setTop(lblTitle);//--- Text-Area
txaMsg.setWrapText(true);
txaMsg.setPrefColumnCount(15);
txaMsg.setPrefRowCount(10);
root.setCenter(txaMsg);
7/23/2019 Java FX Partie6
28/50
Event Handling [2]
IHM-1 FX05 Jacques BAPST 28
//--- Button Panel
btnPanel.getChildren().add(btnInsert);
btnPanel.getChildren().add(btnDelete);
btnPanel.getChildren().add(btnQuit);
btnPanel.setAlignment(Pos.CENTER_RIGHT);
btnPanel.setPadding(newInsets(10, 0, 0, 0));
root.setBottom(btnPanel);
Scenescene= newScene(root);
primaryStage.setScene(scene);
primaryStage.show();
Code de l'interface sans lagestion des vnements.
7/23/2019 Java FX Partie6
29/50
Event Handling [3]
Pour traiter les vnements des boutons, on peut crer une classe
contrleurqui implmente EventHandler et effectue les oprationssouhaites dans la mthode handle().
IHM-1 FX06 Jacques BAPST 29
public classInsertButtonControllerimplementsEventHandler {
privateTextAreatArea;
//--- Constructeur ---------------------------------publicInsertButtonController(TextAreatArea) {
this.tArea= tArea;
}
//--- Code excut lorsque l'vnement survient ----
@Override
public voidhandle(ActionEventevent) {tArea.appendText("A");
}
}
Si on veut agir sur des
composants de la vue,
il faut transmettre les
rfrences ncessaires.
Si le code est plus complexe,
on invoquera de prfrence
une mthode de la vue.
7/23/2019 Java FX Partie6
30/50
Event Handling [4]
Dans la vue, il faut ensuite crer une instance de ce contrleur et
l'enregistrer comme gestionnaire d'vnement (type ACTION) sur lebouton concern en invoquant la mthode addEventHandler().
A chaque clic sur le bouton Insert, legestionnaire d'vnement sera excutet un caractre 'A' sera ajout dans lecomposant TextArea.
IHM-1 FX06 Jacques BAPST 30
. . .
//--- Button Events Handling
InsertButtonControllerinsertCtrl= newInsertButtonController(txaMsg);
btnInsert.addEventHandler(ActionEvent.ACTION, insertCtrl);. . .
7/23/2019 Java FX Partie6
31/50
Event Handling [5]
Une autre manire de faire consiste crer le contrleur sous la
forme d'une classe locale anonyme. Par exemple, pour le boutonDelete :
A chaque clic sur le bouton Delete, legestionnaire d'vnement sera excutet un caractre sera supprim dans lecomposant TextArea.
IHM-1 FX06 Jacques BAPST 31
. . .
//--- Button Events Handling
btnDelete.addEventHandler(ActionEvent.ACTION,
newEventHandler() {
@Overridepublicvoidhandle(ActionEventevent) {
txaMsg.deletePreviousChar();
}
});. . .
7/23/2019 Java FX Partie6
32/50
Event Handling [5]
Une troisime possibilit pour traiter les vnements des boutons,
est d'utiliser la mthode setOnAction() et passer en paramtreune expression lambda implmentant la mthode handle() del'interface EventHandler.
Par exemple pour traiter les trois boutons de l'interface :
IHM-1 FX06 Jacques BAPST 32
//--- Button Events HandlingbtnInsert.setOnAction(event-> {
txaMsg.appendText("A");
});
btnDelete.setOnAction(event-> {
txaMsg.deletePreviousChar();
});
btnQuit.setOnAction(event-> {
Platform.exit();
});
7/23/2019 Java FX Partie6
33/50
Classe 'contrleur'
Dans la variante MVC synchrone, il est frquent que la classe du
contrleur reoive dans son constructeur les rfrences du modleet de la vue.
IHM-1 FX06 Jacques BAPST 33
public classButtonControllerimplementsEventHandler {
privateAppModelmodel;
privateMainViewview;
//--- Constructeur -------------------------------------------
publicButtonController(AppModelmodel, MainViewview) {
this.model= model;
this.view = view;
}
//--- Code excut lorsque l'vnement survient --------------
@Overridepublic voidhandle(ActionEventevent) {
intnewVal= model.getInfo();
view.updateInfo(newVal);
}
}
Rfrences du
modle et de la vue.
Le contrleur accde
aux donnes du modle
et met jour la vue.
7/23/2019 Java FX Partie6
34/50
Mthodes setOn() [1]
Liste des principales actions associes des mthodes utilitaires qui
permettent d'enregistrer des gestionnaires d'vnements (il fautrechercher les mthodes setOnEventType() dans la classe).
IHM-1 FX06 Jacques BAPST 34
Action de l'utilisateur vnement Dans classe
Pression sur une touche du clavier KeyEvent Node, SceneDplacement de la souris ou pression sur une
de ses touches MouseEvent Node, SceneGlisser-dposer avec la souris (Drag-and-Drop)MouseDragEvent Node, SceneGlisser-dposer propre la plateforme (gestepar exemple)
DragEvent Node, Scene
Composant "scroll" ScrollEvent Node, Scene
Geste de rotation RotateEvent Node, Scene
Geste de balayage/dfilement (swipe) SwipeEvent Node, SceneUn composant est touch TouchEvent Node, SceneGeste de zoom ZoomEvent Node, SceneActivation du menu contextuel ContextMenuEventNode, Scene
7/23/2019 Java FX Partie6
35/50
7/23/2019 Java FX Partie6
36/50
Fantas'TIP [1]
Exemple d'application pour illustrer diffrentes manires de raliser
le dcoupage du code en exploitant plusieurs des techniques quisont disposition (classes EventHandler, expressions lambda, binding deproprits, ), tout en respectant les principes de l'architecture MVC.
L'application Fantas'TIP est un utilitaire qui calcule le pourboire prvoir et le montant par personne, en fonction du montant de la
note, du pourcentage octroy et du nombre de convives.
IHM-1 FX06 Jacques BAPST 36
7/23/2019 Java FX Partie6
37/50
Fantas'TIP [2]
Quatre variantes de cette application ont t cres :
Variante 1 : Avec un contrleur ralis sous forme de classe 'ordinaire' Variante 2 : Avec un contrleur ralis sous forme d'expression lambda
Variante 3 : Avec un contrleur ralis sous forme de liaisons de haut-niveau (high-level binding) entre les donnes d'entre(saisies par l'utilisateur) et les donnes de sortie (calcules)
Variante 4 : Avec un contrleur ralis sous forme de liaisons de bas-niveau (low-level binding) entre les donnes d'entre(saisies par l'utilisateur) et les donnes de sortie (calcules)
Quelques extraits de code (les lments importants) figurent dans lespages qui suivent.
L'intgralit du code source des applications est disponible sur la page :http://jacques.bapst.home.hefr.ch/ihm1/src/chap06_FantasTIP
Les applications (excutables) sont disponibles sur la page :http://jacques.bapst.home.hefr.ch/ihm1/applic/fantastip
IHM-1 FX06 Jacques BAPST 37
http://jacques.bapst.home.hefr.ch/ihm1/src/chap06_FantasTIPhttp://jacques.bapst.home.hefr.ch/ihm1/applic/fantastiphttp://jacques.bapst.home.hefr.ch/ihm1/applic/fantastiphttp://jacques.bapst.home.hefr.ch/ihm1/src/chap06_FantasTIP7/23/2019 Java FX Partie6
38/50
Fantas'TIP [3]
Variante 1 : modle de l'application
Interface du modle Classe implmentant cette interface
IHM-1 FX06 Jacques BAPST 38
public interfaceIFantasTipModel{
void setBill(doubleamount);
void setTipPercent(intpercent);
void setNbPeople(intnbPeople);
doublegetTipPerPerson();
doublegetTotalPerPerson();
}
public classFantasTipModelimplementsIFantasTipModel {
private double bill = 0;
private int tipPercent = 0;
private int nbPeople = 1;
//----------------------------------------------------------------------------
publicFantasTipModel() {
}
//----------------------------------------------------------------------------
@Override
public voidsetBill(doubleamount) {
if(amount< 0) throw newIllegalArgumentException("Amount < 0");
this.bill= amount;
}
7/23/2019 Java FX Partie6
39/50
Fantas'TIP [4]
IHM-1 FX06 Jacques BAPST 39
//----------------------------------------------------------------------------
@Override
public voidsetTipPercent(intpercent) {
if(percent< 0) throw newIllegalArgumentException("Percent < 0");
this.tipPercent= percent;
}
//----------------------------------------------------------------------------
@Override
public voidsetNbPeople(intnbPeople) {
if(nbPeople
7/23/2019 Java FX Partie6
40/50
7/23/2019 Java FX Partie6
41/50
Fantas'TIP [6]
Variante 1 : cration d'une instance du contrleur et association au
bouton Calculate. Ces activits sont effectues dans le code de la vue (la mthode privecreateController() est appele dans la mthode start()).
IHM-1 FX06 Jacques BAPST 41
. . .
//----------------------------------------------------------------------------
// Create button controller instance and associate it to button
//----------------------------------------------------------------------------
private voidcreateController(){
controller= newFantasTipController(model, this);
btnCalc.setOnAction(controller);
}
. . .
7/23/2019 Java FX Partie6
42/50
Fantas'TIP [7]
Variante 2 : le contrleur est cr sous forme d'expression lambda.
L'expression lambda est crite dans le code de la vue (la mthodecreateController() est appele dans la mthode start()).
IHM-1 FX06 Jacques BAPST 42
. . .
//----------------------------------------------------------------------------
// Create button controller with lambda expression
//----------------------------------------------------------------------------
private voidcreateController(){
btnCalc.setOnAction(event-> {try{
doublebill = getBillValue();
int tipPercent= getTipPercentValue();
int nbPeople = getNbPeopleValue();
model.setBill(bill);
model.setTipPercent(tipPercent);
model.setNbPeople(nbPeople);
}
catch(IllegalStateExceptione) { // Errors in some input valuesreturn;
}
//--- Update view with values from model output data
updateTipPerPerson(model.getTipPerPerson());
updateTotalPerPerson(model.getTotalPerPerson());
});
}
Mme si le code ducontrleur est critdans le fichier sourcede la vue, l'expressionlambda constitue bienun contrleur qui serareprsent par uneinstance d'une classeanonyme qui
implmente l'interfaceEventHandler.
7/23/2019 Java FX Partie6
43/50
7/23/2019 Java FX Partie6
44/50
7/23/2019 Java FX Partie6
45/50
Fantas'TIP [10]
Variante 3 : mthode createViewModelBindings() appele dans la
mthode start() pour crer les liaisons entre les proprits.
IHM-1 FX06 Jacques BAPST 45
. . .
private voidcreateViewModelBindings(){
//--- Bind view text data with model number data (converter needed)
tfdBill.textProperty().bindBidirectional(model.getBillPty(),
dsConverter());
tfdTipPct.textProperty().bindBidirectional(model.getTipPercentPty(),
isConverter());
tfdNbPple.textProperty().bindBidirectional(model.getNbPeoplePty(),isConverter());
//--- Bind 'output' model properties to calculated properties
model.getTipPerPersonPty().bind(model.getBillPty()
.multiply(model.getTipPercentPty())
.divide(100)
.divide(model.getNbPeoplePty()));
model.getTotalPerPersonPty().bind((model.getBillPty()
.divide(model.getNbPeoplePty()).add(model.getTipPerPersonPty())));
//--- Bind TextField properties to model properties converted to String
tfdRTip.textProperty().bind(model.getTipPerPersonPty().asString());
tfdRTotal.textProperty().bind((model.getTotalPerPersonPty().asString()));
}
7/23/2019 Java FX Partie6
46/50
7/23/2019 Java FX Partie6
47/50
7/23/2019 Java FX Partie6
48/50
7/23/2019 Java FX Partie6
49/50
Fantas'TIP [14]
Variante 4 : mthode strTipPerPersonBinding() qui retourne une
spcialisation de StringBinding (qui convertit et formate la valeur).
IHM-1
FX06
Jacques BAPST 49
. . .
//----------------------------------------------------------------------------
// Low-level binding (convert TipPerPerson to formatted string)
//----------------------------------------------------------------------------
privateStringBindingstrTipPerPersonBinding() {
StringBindingstrBinding= newStringBinding() {
{super.bind(model.getTipPerPersonPty());
}
@Override
protectedString computeValue() {
doubletipPP = model.getTipPerPersonPty().get();
if(tipPP< 0) return"n/a";
String fmtRes= String.format("%.2f", tipPP);
returnfmtRes;
}
};
returnstrBinding;
}
'
7/23/2019 Java FX Partie6
50/50
Fantas'TIP [15]
Variante 4 : mthode createViewModelBindings() qui effectue
l'ensemble des liaisons entre les diffrentes proprits.. . .
//----------------------------------------------------------------------------
// Create all bindings (view-model-view)
//----------------------------------------------------------------------------
private voidcreateViewModelBindings() {
//--- Bind view text data with model number data (converter needed)
tfdBill.textProperty().bindBidirectional(model.getBillPty(),
dsConverter());tfdTipPct.textProperty().bindBidirectional(model.getTipPercentPty(),
isConverter());
tfdNbPple.textProperty().bindBidirectional(model.getNbPeoplePty(),
isConverter());
//--- Bind 'output' model properties to low-level calculated properties
model.getTipPerPersonPty().bind(dblTipPerPersonBinding());
model.getTotalPerPersonPty().bind(dblTotalPerPersonBinding());
//--- Bind TextField properties to model properties converted to String
tfdRTip.textProperty().bind(strTipPerPersonBinding());
tfdRTotal.textProperty().bind(strTotalPerPersonBinding());
}