Upload
trannhan
View
233
Download
3
Embed Size (px)
Citation preview
MVC_Swing_JSF1
MVC et Swing(en rappel)Introduction à JSF
Notes de cours
jean-michel Douin, douin au cnampoint frversion : 31 Octobre 2013
MVC_Swing_JSF2
Sommaire
• Evènements, MVC– Usage des patrons
• Observateur, Commande
– Mise en œuvre du Modèle, Vue, Contrôleur– Exemples
• Démonstration
– Le modèle devient un java Bean– MVC d’un composant swing
• L’API Swing– Un descriptif– Exemples
• Démonstration
– Usage des patrons • Composite, stratégie, fabrique …
• JSF présentation– IHM et HTML
• Du swing côté serveur �� de l’HTML côté client
– MVC et Web
MVC_Swing_JSF3
Principale bibliographie utilisée
• Swing, recherche google– http://notes.corewebprogramming.com/student/Basic-Swing.pdf– mathinfo.ens.univ-reims.fr/.../ppt /Swing _et_les_Applications_Graphiques.ppt
• JSF– Mastering JavaServer Faces, ed Wiley
• Bill Dudney,Jonathan Lehr, Bill Willis, LeRoy Mattingly
– JSF-2• http://andyschwartz.wordpress.com/2009/07/31/whats-new-in-jsf-2/• http://javaserverfaces.java.net/presentations/jsf2-complete-tour/jsf2-complete-tour.pdf
– Divers• Certains diagrammes UML : http://www.dofactory.com/Patterns/PatternProxy.aspx• informations générales http://www.edlin.org/cs/patterns.html
MVC_Swing_JSF4
MVC, doc de Sun
• http://java.sun.com/blueprints/patterns/MVC-detaile d.html• Un exemple …
MVC_Swing_JSF5
Interactivité, MVC
• L’interface graphique– La vue
• Interactions avec l’utilisateur– Le contrôle
• Les données de l’application– Le modèle
• A la recherched’une adéquation des données de l’application et de s vues
– Paradigme MVC• Modèle Vue Contrôleur
MVC_Swing_JSF6
MVC un exemple : un nombre !
le modèle: un nombre
Une vueune jauge
• Déploiement ?– IHM ?– Contrôle ?– Modèle ?
50
Un contrôle
37Une vue
37Une JFrame
MVC_Swing_JSF7
Déploiement ? Choix de classes
• Discussion …– Le modèle : la classe Nombre– La Vue : Une JFrame, une jauge, un affichage, des b outons– Le Contrôle : Réactions aux actions de l’utilisateu r …
MVC_Swing_JSF8
Un déploiement possible, démonstration
• La classe Nombre est Observable– Elle hérite de java.util.Observable
• Les Vues sont des observateurs– Elles implémentent java.util.Observer,– Peuvent être des IHM, des « Container » swing,– Sans interface : des vues sans être vues ?…
• Par exemple : un journal des évènements– …
• Les Contrôles gèrent les actions de l’utilisateur– Elles implémentent les XXXXListener des composants s wing– Une classe par action ?
MVC_Swing_JSF9
Exemple un nombre, une vue, un contrôle
public class MainNombreMVC{
public static void main(String[] args){Nombre nombre = new Nombre(0,10); // le modèle
Vue1 vue1 = new Vue1(nombre);
ControleVue1 controle1 = new ControleVue1(nombre, v ue1);
}}
MVC_Swing_JSF10
Le modèlepublic class Nombre extends java.util.Observable{
public final int VALEUR_MIN;public final int VALEUR_MAX;private int valeur;
public Nombre(int min, int max){this.VALEUR_MIN = this.valeur = min;this.VALEUR_MAX = max;
}
public void inc(){if(valeur < VALEUR_MAX){
this.valeur++;setChanged();notifyObservers();
}}
public void dec(){ // idem -- …… getValeur() + setValeur(…) + toString()
MVC_Swing_JSF11
La Vue est une JFrame et implémente Observer
public class Vue1 extends JFrame implements Observer{
private JButton plus;private JButton moins;private JTextField valeur;private JSlider jauge;
public Vue1(Nombre nombre) {super("Vue1 Nombre");nombre.addObserver(this);
// Mise en place des composants graphiques
pack();setVisible(true);
}
en quelques lignes …, un arbre instance du composite
MVC_Swing_JSF12
La Vue implémente java.util.Observer
@Overridepublic void update(Observable obs, Object arg){if(obs instanceof Nombre){
Nombre n = (Nombre)obs;this.valeur.setText(n.toString());this.jauge.setValue(n.getValeur());
} }
// accesseurspublic JButton getPlus(){return plus;}public JButton getMoins(){return moins;}
}
MVC_Swing_JSF13
Le Contrôle implémente les XXXXListener
public class ControleVue1{private Nombre nombre;
public ControleVue1(Nombre nombre, Vue1 vue){this.nombre = nombre;vue.getMoins(). addActionListener(
new ActionListener(){public void actionPerformed(ActionEvent ae){
ControleVue1.this.nombre.dec();}
});
vue.getPlus(). addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent ae){ControleVue1.this.nombre.inc();
}});
}} adéquation actions de l’utilisateur / opérations su r le modèle
MVC_Swing_JSF14
Démonstration
• Démonstration
• MVC pourquoi faire ?
– Paradigme au-delà de la maturité ?• L’original en 1978 http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-inde x.html
Donner l’illusion à l’utilisateur de manipuler les données du modèle
MVC_Swing_JSF15
Une nouvelle vue, un nouveau contrôle, critiques
public class MainNombreMVC{
public static void main(String[] args){Nombre nombre = new Nombre(0,10); // le modèle
Vue1 vue1 = new Vue1(nombre); ControleVue1 controle1 = new ControleVue1(nombre, v ue1);
Vue2 vue2 = new Vue2(nombre); ControleVue2 controle2 = new ControleVue2(nombre, v ue2);
}}
l’utilisateur peut maintenant modifier la valeur … ajout d’un observateur auprès d’un JTextField
soit jTextField.addActionListener…
MVC_Swing_JSF16
La classe Vue2, est un observateurpublic class Vue2 extends JFrame implements Observer {
private JTextField valeur;private JSlider jauge;
public Vue2(Nombre nombre) {super("Vue2 Nombre");nombre.addObserver(this);Container content = getContentPane();
}
public void update(Observable obs, Object arg){if(obs instanceof Nombre){ // instanceof prévention …
Nombre n = (Nombre)obs;this.valeur.setText(n.toString());this.jauge.setValue(n.getValeur());
} }public JTextField getValeur(){return valeur;}}
en quelques lignes …
MVC_Swing_JSF17
Le Contrôle2 de la vue 2, implements XXXXListener
public class ControleVue2{private Nombre nombre;private Vue2 vue2;
public ControleVue2(Nombre nombre, Vue2 v){this.nombre = nombre;this.vue2 = v;
vue2.getValeur(). addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){try{
int valeur = Integer.parseInt(vue2.getValeur().getTe xt());ControleVue2.this.nombre.setValeur(valeur);
}catch(NumberFormatException nfe){}
}});
}}
Une nouvelle vue engendre ici une nouvelle classe de contrôle, critiques ?Faire autrement ? mieux ?
MVC_Swing_JSF18
Deux nombres … 4 vues, 4 Contrôles
public class MainNombreMVC{
public static void main(String[] args){Nombre nombre = new Nombre(0,10); // le modèleVue1 vue1 = new Vue1(nombre); ControleVue1 controle1 = new ControleVue1(nombre, v ue1);Vue2 vue2 = new Vue2(nombre); ControleVue2 controle2 = new ControleVue2(nombre, v ue2);Vue1 vue11 = new Vue1(nombre);ControleVue1 controle11 = new ControleVue1(nombre, vue11);
Nombre nombreBis = new Nombre(0,100); Vue1 vueBis = new Vue1(nombreBis); ControleVue1 controle = new ControleVue1(nombreBis, vueBis);
}}
Démonstration …
Un dernier exemple : deux nombres … 8 vues, 25 Contrôles, non merci
MVC_Swing_JSF20
Discussion sur l’implémentation du Modèle
• public class Nombre …
• Le Modèle est une classe– Cette classe hérite de java.util.Observable sur cet exemple
• Ce modèle peut devenir un composant logiciel– Un JavaBean
– Peu de différences à part quelques règles d’écritur es• Ces règles permettront une utilisation de ce compos ant par des outils,• Vers une meilleure réutilisation ?• Vers une industrie du composant logiciels ?
– EJB ? Enterprise JavaBeans
» Un nouveau langage au dessus de Java?
MVC_Swing_JSF21
Observable/Observer à la mode JavaBeans
• Paquetage java.beans
• Champs d’instance– int valeur comme property
• Observer comme PropertyChangeListener– public void update (Observable obs, Object o)comme– public void propertyChange (PropertyChangeEvent evt)
• Observable comme PropertyChangeSupport– void notifyObservers (Object o)comme– void firePropertyChange (String property,Object oldValue,Object newValue)
MVC_Swing_JSF22
Un bean
• Un Bean est avant tout une classe …– Un bean est un (extends) POJO, une classe quelconque
Avec
• Le respect de certaines conventions• implements Serializable• Un constructeur par défaut• Un getter et/ou un setter pour chaque variable d’instance• firePropertyChange au sein du setter
• Simple n’est-ce pas ?
• La suite– Nombre devient Bean– La BeanBox, l’outil d’assemblage de Beans : un outil historique– Introspection systématique
MVC_Swing_JSF23
La classe Nombre devient Bean : NombreBeanpublic class NombreBean implements Serializable {
public final int VALEUR_MIN;public final int VALEUR_MAX;private int valeur;private PropertyChangeSupport propertySupport;
public NombreBean(){this.VALEUR_MIN = this.valeur = 0;this.VALEUR_MAX = 10;this.propertySupport = new PropertyChangeSupport(thi s);
}
public void inc(){if(valeur < VALEUR_MAX){
int old = valeur;this.valeur++;propertySupport.firePropertyChange("valeur",old,val eur);
}}
public void addPropertyChangeListener(PropertyChange Listener l) {propertySupport.addPropertyChangeListener(l);
}// public int getValeur() et setValeur()
MVC_Swing_JSF24
La Vue est à l’écoute de son Bean
public class Vue1Bean extends JFrame implements PropertyChangeListener{
private JButton plus;private JButton moins;private JTextField valeur;private JSlider jauge;
public Vue1Bean(NombreBean nombre) {super("Vue1 Nombre");nombre.addPropertyChangeListener(this);
// Le dessin ici}
@Overridepublic void propertyChange(PropertyChangeEvent evt){
assert evt.getPropertyName().equals("valeur");this.valeur.setText(evt.getNewValue().toString());this.jauge.setValue((Integer)evt.getNewValue());
}
Les contrôles ne changent pas, le MVC reste en l’ét at
MVC_Swing_JSF25
NombreBean intègre la BeanBox
• Ajout par l’outil BeanBox d’un listener (EventMonitor ) à chaque changement de valeur de valeur …
démonstration pour l’histoire c’est un outil du siè cle dernier
Usage de l’introspection
setValeurgetValeur
MVC_Swing_JSF26
Usage de l’introspection
Affecter la propriété d’un bean
Object obj une instanceString name le nom de la propriétéint value la nouvelle valeur
public void setProperty(Object obj, String name, int v alue) { String prop = Character.toUpperCase(name.charAt(0)) + name.substring(1);
String mname = "set" + prop;
Class[] types = new Class[] { int.class };
Method method = obj.getClass().getMethod(mname, types );
method.invoke(obj, new Object[] { value });
}
MVC_Swing_JSF28
Conclusion ? discussion
• MVC au niveau d’une application
• Et Il y a aussi un MVC au niveau de chaque composan t swing
MVC_Swing_JSF29
L’API Swing
• Présentation « déclarative »
• Le package javax.swing
• Les composants graphiques
• Quelques exemples en « direct »
– Avertissement : • Présentation à de l’API Swing « orientée » JSF
MVC_Swing_JSF30
Sommaire
• Evènements, MVC– Usage des patrons
• Observateur, Commande
– Mise en œuvre du Modèle, Vue, Contrôleur– Exemples
• Démonstration
– Le modèle devient un java Bean– MVC d’un composant swing
• L’API Swing // Saut possible en diapositive 62 ou 94– Un descriptif– Exemples
• Démonstration
– Usage des patrons • Composite, stratégie, fabrique …
• JSF présentation– IHM et HTML
• Du swing côté serveur �� de l’HTML côté client
– MVC et Web
MVC_Swing_JSF32
Le paquetage swing bien nommé
• javax.swingComposants élémentairesMenus, Barre d’outils et
ToolTipsContainers
• javax.swing.beaninfo• javax.swing.beaninfo.images• javax.swing.border• javax.swing.colorchooser• javax.swing.event
• javax.swing.filechooser• javax.swing.plaf • javax.swing.plaf.basic • javax.swing.plaf.metal• javax.swing.plaf.multi• javax.swing.table • javax.swing.text • javax.swing.text.html• javax.swing.tree• javax.swing.undo
MVC_Swing_JSF33
Hiérarchie de classes 1/2, tout est JComponent
• Container– JComponent
• AbstractButton– JButton– JMenuItem
» JCheckBoxMenuItem
» JMenu
» JRadioButtonMenuItem– JToggleButton
» JCheckBox
» JRadioButton
MVC_Swing_JSF34
Hiérarchie 2/2, JComponent suite
• JComponent– JComboBox– JLabel– JList– JMenuBar– JPanel– JPopupMenu– JScrollBar– JScrollPane– JTextComponent
• JTextArea• JTextField
– JPasswordField• JTextPane
– JHTMLPane
MVC_Swing_JSF35
Autres Composants, toujours des JComponent
• JRootPane• JSeparator• JSlider• JSplitPane• JTabbedPane• JTable• JToolBar• JToolTip• JTree• JViewport
• FontChooser• JColorChooser• JDesktopIcon• JDirectoryPane
– JFileChooser
• JImagePreviewer• JInternalFrame• JLayeredPane
– JDesktopPane
• JOptionPane• JProgressBar
MVC_Swing_JSF36
Exemples 1/3, en images
• Menus, Barre d’outils et ToolTips
– JMenuBar– JMenu– JMenuItem– JCheckBoxMenuItem– JRadioButtonMenuItem– JPopupMenu– JToolBar– JToolTip
MVC_Swing_JSF37
Exemples 2/3
• Composants Textes
– JPasswordField– JTextField– JTextArea– JTextPane– JEditorPane
MVC_Swing_JSF38
Exemples 3/3
• Containers
– JOptionPane– JDialog– JTabbedPane– JSplitPane– JScrollPane– JFrame– JInternalFrame– JDesktopPane– JWindow
MVC_Swing_JSF39
Hiérarchie, suite, top-level et les autres
• Les “Top Level containers” et les autres– JDialog , JFrame , JWindow , JApplet , JInternalFrame
• héritent de Window
• Les autres sont des JComponent– Ils sont ajoutés au “ content pane ” d’un “ top level container “ …
MVC_Swing_JSF40
RootPaneContainer
• Pas d’ajout direct au container (top level)– aFrame.add (new Button (“Help”)); � non
• Ajout au “ content pane ” – aJFrame.getContentPane().add ( new Button (“Help”)); � oui
– RootPaneContainer définit la méthode getContentPane• Implétentée par
– public Container getContentPane() { return getRootPane().getContentPane(); }
• Les top-level– JDialog , JFrame , JWindow , JApplet , JInternalFrame
MVC_Swing_JSF41
Un exemple
import javax.swing.JFrame;import javax.swing.JButton;import javax.swing.JLabel;
import java.awt.Container;import java.awt.FlowLayout;import java.awt.Button;
public class FrameTester {public static void main (String args[]) {
JFrame f = new JFrame ("Exemple de JFrame");Container c = f.getContentPane();c.setLayout (new FlowLayout()); // placement des objets (à suivre)
for (int i = 0; i < 5; i++) {c.add (new JButton (Integer.toString(i))); // swingc.add (new Button (Integer.toString(i))); // awt
}c.add (new JLabel ("Swing"));f.setSize (300, 200);f.show();
}}
f.getContentPane();
MVC_Swing_JSF43
Disposition des objets dans un « container »
• LayoutManager– FlowLayout, BorderLayout, GridLayout
• Composite, Strategy deux Patrons ? À suivre …
B u tto n( fro m a w t )
B o rd e rL a y o u t( fro m a w t )
C o m p o n e n t( fro m a w t )
G r i d L a y o u t( fro m a w t )
L a y o u tM a n a g e r2( fro m a w t )
< < In te r fa c e > >
C o n ta i n e r( fro m a w t )
c o m p o n e n t[]
L a y o u tM a n a g e r( fro m a w t )
< < In te r fa c e > >la y o u tM g r
Composite ?
Strategy ?
MVC_Swing_JSF45
BorderLayout
En 5 zonesBorderLayout.NORTH
BorderLayout.WEST BorderLayout.CENTER, BorderLayout.EAST
BorderLayout.SOUTH
MVC_Swing_JSF48
Un exemple d’IHM : une JApplet
• Deux boutons , un texte , une liste
JApplet
JPanel (ContentPane)
JButton JButton JPanel
JScrollPaneJTextField
JList
MVC_Swing_JSF49
Exemple, Deux boutons, un texte, une liste
// quelques déclarations
JPanel contentPane;
JButton jButton1 = new JButton();
JButton jButton2 = new JButton();
JTree jTree1 = new JTree();
JTextField jTextField1 = new JTextField();
JPanel jPanel1 = new JPanel();
JScrollPane jScrollPane1 = new JScrollPane();
BorderLayout borderLayout1 = new BorderLayout();
MVC_Swing_JSF50
Construction de l’arbre …
contentPane = this.getContentPane(); // this est une JApplet
contentPane.add(jButton1, null);contentPane.add(jButton2, null);contentPane.add(jPanel1, null);
jPanel1.add(jScrollPane1, BorderLayout.CENTER );jPanel1.add(jTextField1, BorderLayout.NORTH );jScrollPane1.getViewport().add(jTree1, null);
MVC_Swing_JSF51
Divers : de JApplet en JFrame
static void run(JApplet applet, int width, int height) {
JFrame frame = new JFrame();frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add(applet);frame.setSize(width, height);
applet.init();applet.start();frame.setVisible(true);
}
L’arbre change de racine …
MVC_Swing_JSF52
Un autre exemple : Un formulaire
public class LoginForm extends JFrame {
public LoginForm() {super("LoginForm");Container contents = getContentPane();
// contents.setLayout(new BorderLayout()); // par d éfaut
contents.add( getLoginPanel (), BorderLayout.CENTER);contents.add( getButtonPanel (), BorderLayout.SOUTH);pack(); setVisible(true);
}
MVC_Swing_JSF53
Le dessin suite ……
public JPanel getLoginPanel() {JPanel panel = new JPanel(new BorderLayout());JPanel labelPanel = new JPanel(new GridLayout(2,0));JLabel userIdLabel = new JLabel("User ID:");labelPanel.add(userIdLabel);JLabel passwordLabel = new JLabel("Password:");labelPanel.add(passwordLabel);panel.add(labelPanel, BorderLayout.WEST);JPanel fieldPanel = new JPanel(new GridLayout(2,0));JTextField userIdField = new JTextField(10);fieldPanel.add(userIdField);JPasswordField passwordField = new JPasswordField(10);fieldPanel.add(passwordField);panel.add(fieldPanel, BorderLayout.CENTER);return panel;
}
public JPanel getButtonPanel() {JPanel panel = new JPanel(new FlowLayout());JButton okButton = new JButton("OK");panel.add(okButton); return panel;
}
MVC_Swing_JSF55
Autres composants
• À suivre
• Fenêtres de dialogues– JOptionPane
• Apparence des objets graphiques– Apparence « windows », Metal,– UIManager.setLookAndFeel
MVC_Swing_JSF57
Un exemple
import javax.swing.JOptionPane;
public class JOption{
public static void main(String[] args) {
Object response = JOptionPane.showInputDialog(null, "au choix", "Titre",
JOptionPane.QUESTION_MESSAGE,
null,
new Object[] { "Amandes", "Noisettes", "Noix"}, "No ix");
// response = ( "Amandes" | "Noisettes" | "Noix" | n ull)
}
}
MVC_Swing_JSF58
Au choix
• Lecture bloquante … jusqu’à ce que l’utilisateur
Unification des 3 précédents.showOptionDialog
Une indication.showMessageDialog
Demande un choix (c.f. exemple précédent).showInputDialog
Pose une question oui/non/annuler.showConfirmDialog
DescriptionMéthode
MVC_Swing_JSF59
Les Apparences LookAndFeel
• Choix de l’apparence.
– Metal (par défaut)• UIManager.setLookAndFeel("javax.swing.plaf.metal.Me talLookAndFeel");
– Windows• UIManager.setLookAndFeel("com.sun.java.swing.plaf.w indows.WindowsLookAndFeel");
– Apparence Motif• UIManager.setLookAndFeel("com.sun.java.swing.plaf.m otif.MotifLookAndFeel");
MVC_Swing_JSF62
Swing : où sont les patrons ?
• Patron Composite– Construction d’une IHM
• Patron Stratégie– Disposition des objets graphiques
MVC_Swing_JSF64
Le patron Composite, rappel
• Structures de données récursives– Un Composant est une feuille ou un composite– Un Composite est un Composant
MVC_Swing_JSF67
list() comme operation()
• Méthode de la classe Component quelque soit l’arbre
• Component loginForm = new LoginForm ();• loginForm.list();
LoginForm[frame0,0,0,183x103,layout=java.awt.BorderLayout,title=LoginForm,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,4,23,175x76,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
javax.swing.JRootPane[,4,23,175x76,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=]
javax.swing.JPanel[null.glassPane,0,0,175x76,hidden,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777217,maximumSize=,minimumSize=,preferredSize=]
javax.swing.JLayeredPane[null.layeredPane,0,0,175x76,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,optimizedDrawingPossible=true]………………
MVC_Swing_JSF68
Retour sur L’original
• Méthode Operation()– Component c = … une feuille ou un composite– C.Operation();
• Notons l’accès aux enfants depuis un nœud composite , classe Component– Méthode getChild
MVC_Swing_JSF69
Le patron Strategy
• Context ctxt = new Context(new ConcreteStrategyB());– Le champ d’instance aStrategy est affecté par l’argument du constructeur
Puis• ctxt.contextInterface();
– Retournera un AlgorithmInterface () concret
MVC_Swing_JSF70
Le patron Strategy et les « layout »
• Exemple :– Container content = getContentPane();– content.setLayout(new BorderLayout());
BorderLayout FlowLayout GridLayout
LayoutManagerContainer
MVC_Swing_JSF71
Les images … (encore un patron), en apparté
• Le chargement d’une image peut-être lent…– Si c’est synchrone alors l’application attend
alors un chargement asynchrone s’impose …
• Pour cela usage– Du paradigme Producteur/Consommateur– Du patron observateur
– Une instance de la classe Image n’est pas un tablea u de pixels mais un canal entre un producteur d’image et son consommate ur
– L’image est un observateur, notifiée par le producteur
MVC_Swing_JSF72
ImageObserver
imageUpdate(img : Image, infoflags : int, x : int, y : int, width : int, height : int) : boolean
<<Interface>>
Image
getWidth(observer : ImageObserver) : intgetHeight(observer : ImageObserver) : intgetSource() : ImageProducergetGraphics() : GraphicsgetProperty(name : String, observer : ImageObserver) : ObjectgetScaledInstance(width : int, height : int, hints : int) : Imageflush() : void
Component
FilteredImageSource MemoryImageSource
ImageProducer
addConsumer(ic : ImageConsumer) : voidisConsumer(ic : ImageConsumer) : booleanremoveConsumer(ic : ImageConsumer) : voidstartProduction(ic : ImageConsumer) : voidrequestTopDownLeftRightResend(ic : ImageConsumer) : void
<<Interface>>
src
ImageConsumer
setDimensions()setProperties()setColorModel()setHints()setPixels()setPixels()imageComplete()
<<Interface>>
0..*0..*
BufferedImage
MVC_Swing_JSF73
Un exemple … Aurores boréales au Cnam ?
public class ImageDemo {static public void main(String args[]) throws Exceptio n {
JFrame f= new JFrame("test images");f.getContentPane().add(new MyPanel());f.setSize(300,200);f.setVisible(true);
}
static class MyPanel extends JPanel {private Image m1,m2;public MyPanel() throws MalformedURLException {
Toolkit toolkit=Toolkit.getDefaultToolkit();m1=toolkit.getImage(new URL("http://www.cnam.fr/image s/logo_cnam.gif"));m2=toolkit.getImage(new
URL("http://media.aftenposten.no/archive/00411/_127 4097_jpg_411307h.jpg"));
}public void paintComponent(Graphics g) {Dimension d = getSize();g.drawImage(m2,0,0,this);g.drawImage(m1,0,0,this);
}}}
MVC_Swing_JSF74
Réagir aux clics : le formulaire déjà vu
• Associer une action au clic sur OK– légitime
• Patron observateur/observé– Les « listeners »
MVC_Swing_JSF75
Patron observé/observateur-écouteur( ou listener)
• 1) enregistrement auprès du bouton d’un écouteur– bouton.addActionListener(ActionListener al)
• Plusieurs écouteurs sont possibles
• 2) A chaque clic les écouteurs sont notifiés– al.actionPerformed(ActionEvent ae)
– L’exemple du formulaire suit …
MVC_Swing_JSF76
le patron Observateur, l’original
• http://www.codeproject.com/gen/design/applyingpatterns/observer.gif
MVC_Swing_JSF77
Ajout d’un observateur du bouton
public JPanel getButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
JButton okButton = new JButton("OK");
panel.add(okButton);
okButton.addActionListener(new OkButtonAction());
return panel;
}
}
MVC_Swing_JSF78
OkButton action !!!
class OkButtonAction implements ActionListener{
public void actionPerformed(ActionEvent ae){// Vérification du nom et mot de passe// par exemple …
}
}
Différentes formes syntaxiques possiblesClasse interne et statiqueClasse interne et membreClasse anonyme
MVC_Swing_JSF79
Action, Listeners et les autres, par convention
• Un composant swing enregistre ses écouteurs– addXXXXListener
• Les écouteurs implémentent – L’interface XXXXListener et « sont des » java.awt.event.EventListener
– Cette interface décrit une méthode acceptant en par amètre un XXXXEvent– Chaque écouteur s’enregistre auprès du composant sw ing
• A chaque changement d’état du composant swing– Les méthodes des écouteurs pré-enregistrés sont exéc utées
• Le paramètre XXXXEvent contient au moins la source d e la notification
MVC_Swing_JSF81
Des Adaptateurs à adapter
• Implémenter un XXXXListener peut être fastidieux– Surtout si une seule méthode de l’interface est con cernée …
– Exemple : l’interface WindowListener• public void windowActivated (WindowEvent e) • public void windowClosed (WindowEvent e) • public void windowClosing (WindowEvent e) • public void windowDeactivated (WindowEvent e) • public void windowDeiconified (WindowEvent e) • public void windowIconified (WindowEvent e) • public void windowOpened (WindowEvent e)
– Au total 7 méthodes à implémenter …
• Utile : il existe une classe XXXXAdapter qui impléme nte XXXXListener
– Exemple la classe WindowAdapter
MVC_Swing_JSF82
XXXXAdapter à adapter
• Exemple suite : WindowAdapter– Au clic dans la case de fermeture alors arrêt bruta l du programme– Pas d’action pour les 6 autres méthodes….
Window w = …
w.addWindowListener( new WindowAdapter(){
public void windowClosing(WindowEvent event) { System.exit(0);
}});
MVC_Swing_JSF83
Swing, un constat
C’est une première présentation
• Des composants graphiques• Une gestion des évènements• Un look and feel indépendant
• IHM alors MVC– Modèle Vue Contrôleur
– Comment ?, quel déploiement ?, pourquoi faire ?
MVC_Swing_JSF84
Conclusion, discussion
• MVC– Mature
La suite
• MVC et composant swing– Certains composants proposent de changer le modèle et l’IHM…
• Saut possible en 95
MVC_Swing_JSF85
Un Composant Swing et MVC
• Par exemple– JTextField
• Une zone de texte (classe JTextComponent)
– Le Modèle• Le texte (classe PlainDocument)
– L’interface Utilisateur• Un rectangle (classe BasicTextFieldUI )
• En standard– JTextField field = new JTextField();
• Avec un autre modèle– JTextField field = new JTextField (new unAutreModèleDe Document());
• Avec une autre interface utilisateur (vue)– field.setUI(new uneAutreInterface());
MVC_Swing_JSF86
Un exemple, avec démo possible…
• Le « nouveau » JTextField ne peut contenir que des maju scules !– Une contrainte sur une entrée du formulaire
– Un nouveau modèle, ici une sous-classe de Document– this.userIdField = new JTextField(new UnAutreModèleDeTexte(), "", 10);
public class UnAutreModèleDeTexte extends PlainDocume nt {public void insertString(int offs, String str, Attrib uteSet a)
throws BadLocationException {if (str == null) {
return;}char[] upper = str.toCharArray();for (int i = 0; i < upper.length; i++) {
upper[i] = Character.toUpperCase(upper[i]);}super.insertString(offs, new String(upper), a);
}}
MVC_Swing_JSF89
Component Model Interface Model Type
JButton ButtonModel GUI
JToggleButton ButtonModel GUI/data
JCheckBox ButtonModel GUI/data
JRadioButton ButtonModel GUI/data
JMenu ButtonModel GUI
JMenuItem ButtonModel GUI
JCheckBoxMenuItem ButtonModel GUI/data
JRadioButtonMenuItem ButtonModel GUI/data
JComboBox ComboBoxModel data
JProgressBar BoundedRangeModel GUI/data
JScrollBar BoundedRangeModel GUI/data
JSlider BoundedRangeModel GUI/data
JTabbedPane SingleSelectionModel GUI
JList ListModel data
JList ListSelectionModel GUI
JTable TableModel data
JTable TableColumnModel GUI
JTree TreeModel data
JTree TreeSelectionModel GUI
JEditorPane Document data
JTextPane Document data
JTextArea Document data
JTextField Document data
JPasswordField Document data
MVC_Swing_JSF90
« Model » et Notification…Model Listener Event
ListModel ListDataListener ListDataEvent
ListSelectionModel ListSelectionListener ListSelectionEvent
ComboBoxModel ListDataListener ListDataEvent
TreeModel TreeModelListener TreeModelEvent
TreeSelectionModel TreeSelectionListener TreeSelectionEvent
TableModel TableModelListener TableModelEvent
TableColumnModel TableColumnModel-
Listener
TableColumnModel-
Event
Document DocumentListener DocumentEvent
Document UndoableEditListener UndoableEditEvent
MVC_Swing_JSF92
JL ist
JList()setC ellRenderer()setModel()
JC om ponentC om ponentU I
# ui
L istU I
ListD ataEvent
getType()getIndex0()getIndex1()ListD ataEvent()
BasicListUI
# list
ListModel
g etS ize ()g etE le me ntAt()a dd ListD a taL istene r()rem oveL istD ata Liste ner()
<<Interface>>
-da taM od el
AbstractListM odel
addListD ataListener(l : L istD ataListener) : voidremoveListD ataListener(l : L istD ataListener) : voidfireC ontentsC hanged(source : Object, index0 : int, index1 : int) : voidfireIntervalAdded(source : Object, index0 : int, index1 : int) : voidfireIntervalRemoved(source : Object, index0 : int, index1 : int) : voidgetListeners(listenerType : C lass) : EventListener[]
L istD ataListener
intervalAdded(e : L istD ataEvent) : voidintervalRemoved(e : L istD ataEvent) : voidcontentsC hanged(e : L istD ataEvent) : void
<<Interface>>
#listD ataListener
0..*0..*
MVC_Swing_JSF93
ListD ataListener<<Interface>>
TableModelEventD ELETE : int = - 1INSERT : int = 1UPD ATE : int = 0
getC olumn()getF irstRow()getLastRow()getType()
Tab le Mo de l
getRowC ount()getC olumnC ount()getC olumnName()getC olumnC lass()isC ellEditable()getValueA t()setValueA t()addTableModelListener()removeTableModelListener()
<<Interface>>
AbstractTableM odel
getC olumnName(column : int) : S tringfindC olumn(columnName : S tring) : intgetC olumnC lass(columnIndex : int) : C lassisC ellEditable(rowIndex : int, columnIndex : int) : booleansetValueA t(aValue : Object, rowIndex : int, columnIndex : int) : voidaddTableModelListener(l : TableModelListener) : voidremoveTableModelListener(l : TableModelListener) : voidfireTableD ataC hanged() : voidfireTableS tructureC hanged() : voidfireTableRowsInserted(firstRow : int, lastRow : int) : voidfireTableRowsUpdated(firstRow : int, lastRow : int) : voidfireTableRowsD eleted(firstRow : int, lastRow : int) : voidfireTableC ellUpdated(row : int, column : int) : voidfireTableC hanged(e : TableModelEvent) : voidgetListeners(listenerType : C lass) : EventListener[]
TableModelListener
ta bleC ha nged(e : TableModelEvent) : void
<<Interface>>
0..*0..*
TableU I
JC o m po ne nt
C o m po ne ntU I#ui
BasicTableUI
JTable#dataModel#table
MVC_Swing_JSF94
Sommaire
• Evènements, MVC– Usage des patrons
• Observateur, Commande
– Mise en œuvre du Modèle, Vue, Contrôleur– Exemples
• Démonstration
– Le modèle devient un java Bean– MVC d’un composant swing
• L’API Swing– Un descriptif– Exemples
• Démonstration
– Usage des patrons • Composite, stratégie, fabrique …
• JSF présentation– IHM et HTML
• Du swing côté serveur �� de l’HTML côté client
– MVC et Web
MVC_Swing_JSF95
JSF une introduction
• MVC Web
• JSF – Framework pour applications web– MVC web– Configuration en fichier xml– Mise en place d’un JavaBean adaptateur si nécessaire
MVC_Swing_JSF96
bibliographie
• Mastering JavaServer Faces, 2004 ed Wiley– Bill Dudney,Jonathan Lehr, Bill Willis, LeRoy Mattingly
– La plupart des figures présentes sur ce support sont extraites de ce livre• src : mastering JSF
• Cours de J-L Dewez GLG203/2009
– La plupart des transparents qui suivent sont extraits de ce support
MVC_Swing_JSF97
Evolution des Frameworks
• Servlets - 1997• Procedural JSP - 1999• Composition Frameworks
– Tapestry– 2000
• Action Frameworks– Struts– 2001
• Component Frameworks– JavaServer™ Faces– 2004
MVC_Swing_JSF98
Evolution de l' Architecture Web
1. Modèle 1 (orienté Pages web)
2. Modèle 2 (orienté Servlette de contrôle)
Les frameworks WebStrutsJavaServer Faces comme un standard
MVC_Swing_JSF99
Modèle 1 Orienté page
<html> <head> <script type="text/javascript">
function validate_required(field,alerttxt) {
with (field) { if (value==null||value=="") {alert(alerttxt);return false}
else {return true} } }
function validate_form(thisform) {
with (thisform) { if (validate_required(email,"Email must be filledout!")==false) {email.focus();return false} } }
</script> </head>
<body>
<form action="submitpage.htm" onsubmit="return validate_form(this)"method="post">
Email: <input type="text" name="email" size="30">
<input type="submit" value="Submit">
</form>
</body> </html>
MVC_Swing_JSF105
JSF et swing ?
• Une pensée en jargon swing :– Un JFrame , son contentPane dans lequel la disposition est un
GridLayout , deux JButton, deux JLabel deux JTextField , …
MVC_Swing_JSF106
Exprimée en JSF !, un nouveau langage ?
<f:view><h:form id=”customerForm” >
<h:panelGrid columns=”2”><f:facet name=”header”>
<h:panelGroup><h:outputText id=”header” value=”Customer Name”/>
</h:panelGroup></f:facet><h:panelGroup>
<h:outputText id=”fNameLabel” value=”First Name:”/><h:inputText id=”fName” value=”#{customer.firstName}”/>
</h:panelGroup><h:panelGroup>
<h:outputText id=”lNameLabel” value=”Last Name:”/><h:inputText id=”lName” value=”#{customer.lastName}”/>
</h:panelGroup><h:panelGroup>
<h:commandButton id=”cancel” value=”Cancel”/><h:commandButton id=”save” value=”Save”/>
</h:panelGroup></h:panelGrid>
</h:form></f:view>
MVC_Swing_JSF108
Contrôleur, principe
• Réception des requêtes des clients– FacesServlet
• Configuration• Étapes pour la réponse
1. Restitution de la page1. Si celle-ci a déjà été présentée au client
2. Mise à jour de l’interface (côté serveur)3. Validation, tests des entrées4. Mise à jour du modèle5. Application invoquée
• Interaction avec le JavaBean, EJB,…
6. Construction de la réponse• JSP-View
MVC_Swing_JSF109
Le Modèle, ici un Bean
public final class LoginBean implements Serializable{private String password ;private String userId ;
public String get Password () {return (this.password);}public void set Password (String password) {
this.password = password;}public String get UserId () {return (this.userId);}public void set UserId (String userId) {
this.userId = userId;}public String login() { // success ou failure
if(isValide()) // consultation d’une table …return "success";
elsereturn "failure";
}}
MVC_Swing_JSF110
Contrôleur / config
• Comment appeler le LoginBean ?– Notamment la méthode login ?
• Extrait du faces-config.xml– Installation du Bean, des accesseurs…
<managed-bean><managed-bean-name> login </managed-bean-name><managed-bean-class> LoginBean </managed-bean-class><managed-bean-scope>request</managed-bean-scope><managed-property>
<property-name> userId </property-name></managed-property><managed-property>
<property-name> password </property-name></managed-property>
</managed-bean>
MVC_Swing_JSF111
config
<managed-bean>// le nom pour JSF<managed-bean-name> login </managed-bean-name>// la classe Java<managed-bean-class> LoginBean </managed-bean-class>// portée de cet objet, session , application , request// session une instance par utilisateur// application une seule instance// request une instance par requête<managed-bean-scope>request</managed-bean-scope>// accès aux champs d’instance<managed-property>
<property-name> userId </property-name></managed-property>…
</managed-bean>
MVC_Swing_JSF112
Contrôleur / config / navigation / Vue
• Quel enchaînement des pages souhaité ?– La page login.jsp comme accueil– soit la page home.jsp en cas de succès, success– soit la même page login.jsp si échec, failure
• Extrait du faces-config.xml– Un diagramme d’états
<navigation-rule><from-view-id>/login.jsp</from-view-id>
<navigation-case><from-out-come> sucess </from-out-come>
<to-view-id> /home.jsp </to-view-id></navigation-case>
<navigation-case><from-out-come> failure </from-out-come>
<to-view-id> /login.jsp </to-view-id></navigation-case>
</navigation-rule>
MVC_Swing_JSF113
Le formulaire /login.jsp
<html><head><meta http-equiv=”Content-Type” content=”text/html; charset=iso-8859-1”><title>Login</title>
<%@ taglib uri=”http://java.sun.com/jsf/core/” prefi x=” f ” %><%@ taglib uri=”http://java.sun.com/jsf/html” prefix =” h” %>
</head><body>Log in with your User ID and Password.<br/><br/><f:view><h:form>
<h:outputLabel for=”userId”><h:outputText value=”User ID”/>
</h:outputLabel><h:inputText id=”userId” value=” #{login.userId} ”/><br/><h:outputLabel for=”password”>
<h:outputText value=”Password”/></h:outputLabel><h:inputSecret id=”password” value=” #{login.password} ”/><br/><h:commandButton action=” #{login.login} ” value=”Login”/>
</h:form></f:view></body></html>
Usage deschampsuserIdpassword
La méthode loginCelle-ci retourne une « String »
MVC_Swing_JSF114
IHM-JSF en HTML pour le client
un extrait de login.jsp
<%@ taglib uri=”http://java.sun.com/jsf/html” prefix =” h” %>
c.f. page précédente
<h:inputSecret id=”password” value=” #{login.password} ”/><br/>
• Le client reçoit un texte « de l’HTML »<input id="form:password" name="form:password" type="password" />
Notons que :Côté client ce sont des String …
MVC_Swing_JSF115
Un formulaire HTML / Composite JSF
• Un formulaire HTML est présenté au client
• Côté serveur un composite apparenté swing– est créé– Ou est restauré
– Une instance d’un Composite ?
MVC_Swing_JSF117
Le formulaire devient en interne…
• Mais quels sont ces composants ?• Validation des entrées ?• Appel du Bean (managed_bean) ?• Et les évènements ? • Avons-nous accès à cette structure ?
– À suivre….
MVC_Swing_JSF126
Pause JSF nouveau langage génération de pages HTML ?
• <%@ taglib uri="http://java.sun.com/jsf/html" prefi x="h"%><%@ taglib uri="http://java.sun.com/jsf/core" prefix ="f"%>
<f:view><html>
<body><h:form>
<h:panelGrid columns="3" border="1" rules="all" titl e="This ispanelGrid demo">
<f:facet name="header"><h:outputText value="Fill Numbers Below"/>
</f:facet><h:inputText/><h:inputText/><h:inputText/><h:inputText/><h:inputText/><h:inputText/><h:inputText/><h:inputText/>
</h:panelGrid></h:form>
</body></html>
</f:view>
• src : http://www.roseindia.net/jsf/panelGrid.shtml• f:facet vu ensuite
MVC_Swing_JSF127
En HTML, c’est ce que comprend le client
• <html><body>
<form id="_id0" method="post"enctype="application/x-w ww-form-urlencoded"><table border="1" rules="all" title="This is panelGrid d emo"><thead><tr><th colspan="3" scope="colgroup">Fill Numbers Below </th></tr></thead><tbody><tr><td><input type="text" name="_id0:_id3" /></td><td><input type="text" name="_id0:_id4" /></td><td><input type="text" name="_id0:_id5" /></td></tr><tr><td><input type="text" name="_id0:_id6" /></td><td><input type="text" name="_id0:_id7" /></td><td><input type="text" name="_id0:_id8" /></td></tr><tr><td><input type="text" name="_id0:_id9" /></td><td><input type="text" name="_id0:_id10" /></td></tr></tbody></table>
<input type="hidden" name="_id0" value="_id0" /></form></body>
</html>