Vous êtes sur la page 1sur 95

Swing et MVC

jean-michel Douin, douin au cnam point fr


version : 30 Octobre 2014
Notes de cours

Swing_MVC

Sommaire
LAPI Swing
Un descriptif
Exemples
Dmonstration

Usage des patrons


Composite, stratgie, fabrique

Evnements, MVC
Usage des patrons
Observateur, Commande
Mise en uvre du Modle, Vue, Contrleur
Exemples
Dmonstration
Le modle devient un javaBean
MVC dun composant swing

JSF prsentation
IHM et HTML
Du swing ct serveur

de lHTML ct client

MVC et Web
Swing_MVC

Principale bibliographie utilise


Swing, recherche google
http://notes.corewebprogramming.com/student/Basic-Swing.pdf
mathinfo.ens.univ-reims.fr/.../ppt/Swing_et_les_Applications_Graphiques.ppt

Divers
Certains diagrammes UML : http://www.dofactory.com/Patterns/PatternProxy.aspx
informations gnrales http://www.edlin.org/cs/patterns.html

Swing_MVC

LAPI Swing
Prsentation dclarative
Le package javax.swing
Les composants graphiques
Quelques exemples en direct

Avertissement :
Prsentation de lAPI Swing oriente JSF

Swing_MVC

Swing en images, javax.swing

Swing_MVC

Le paquetage swing bien nomm


javax.swing
Composants lmentaires
Menus, Barre doutils et
ToolTips
Containers

Swing_MVC

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

Hirarchie de classes 1/2, tout est JComponent


Container
JComponent
AbstractButton
JButton
JMenuItem

JCheckBoxMenuItem
JMenu
JRadioButtonMenuItem
JToggleButton

JCheckBox
JRadioButton

Swing_MVC

Hirarchie 2/2, JComponent suite


JComponent

JComboBox
JLabel
JList
JMenuBar
JPanel
JPopupMenu
JScrollBar
JScrollPane
JTextComponent
JTextArea
JTextField
JPasswordField
JTextPane
JHTMLPane

Swing_MVC

Autres Composants, toujours des JComponent

FontChooser
JColorChooser
JDesktopIcon
JDirectoryPane
JFileChooser

JImagePreviewer
JInternalFrame
JLayeredPane
JDesktopPane

JOptionPane
JProgressBar

Swing_MVC

JRootPane
JSeparator
JSlider
JSplitPane
JTabbedPane
JTable
JToolBar
JToolTip
JTree
JViewport

Exemples 1/3, en images


Menus, Barre doutils et ToolTips

Swing_MVC

JMenuBar
JMenu
JMenuItem
JCheckBoxMenuItem
JRadioButtonMenuItem
JPopupMenu
JToolBar
JToolTip

10

Exemples 2/3

Composants Textes

Swing_MVC

JPasswordField
JTextField
JTextArea
JTextPane
JEditorPane

11

Exemples 3/3
Containers

Swing_MVC

JOptionPane
JDialog
JTabbedPane
JSplitPane
JScrollPane
JFrame
JInternalFrame
JDesktopPane
JWindow
12

Hirarchie, suite, top-level et les autres


Les Top Level containers et les autres
JDialog, JFrame, JWindow, JApplet, JInternalFrame
hritent de Window

Les autres sont des JComponent


Ils sont ajouts au content pane dun top level container

Swing_MVC

13

RootPaneContainer
Pas dajout direct au container (top level)
aFrame.add (new Button (Help));

non

Ajout au content pane


aJFrame.getContentPane().add ( new Button (Help));

oui

RootPaneContainer dfinit la mthode getContentPane


Impltente par
public Container getContentPane() { return getRootPane().getContentPane(); }

Les top-level
JDialog, JFrame, JWindow, JApplet, JInternalFrame

Swing_MVC

14

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 {
f.getContentPane();
public static void main (String args[]) {
JFrame f = new JFrame ("Exemple de JFrame");

Container c = f.getContentPane();
c.setLayout (new FlowLayout()); // placement des objets
for (int i = 0; i < 5; i++) {
c.add (new JButton (Integer.toString(i))); // swing
c.add (new Button (Integer.toString(i))); // awt
}
c.add (new JLabel ("Swing"));
f.setSize (300, 200);
f.show();
}}
Swing_MVC

( suivre)

15

ContentPane
Le contenu

Swing_MVC

16

Disposition des objets dans un container


C o m p o ne nt
( fr o m a w t )

c o m p o n e n t[]

Composite ?

B u tto n

C o n ta i n e r

( fr o m a w t )

( fr o m a w t )

la y o u tM g r < < In te r fa c e > >


L a y o u tM a n a g e r
( fr o m a w t )

< < In te r fa c e > >


L a y o u tM a n a g e r2
( fr o m a w t )

G rid L a yo u t
( fr o m a w t )

LayoutManager
FlowLayout, BorderLayout, GridLayout

B o rd e rL a yo u t
( fr o m a w t )

Strategy ?

Composite, Strategy deux Patrons ? suivre


Swing_MVC

17

Les Layout

Swing_MVC

BorderLayout
FlowLayout
GridLayout
CardLayout
.

18

BorderLayout
En 5 zones
BorderLayout .NORTH
BorderLayout .WEST

BorderLayout .CENTER,

BorderLayout .EAST

BorderLayout .SOUTH

Swing_MVC

19

FlowLayout
comme ils viennent

Swing_MVC

20

Grid Layout
En une table

Swing_MVC

21

Un exemple dIHM : une JApplet

JApplet

JPanel (ContentPane)

JButton

JButton

JPanel

JTextField

JScrollPane

JList

Deux boutons, un texte, une liste

Swing_MVC

22

Exemple, Deux boutons, un texte, une liste

// quelques dclarations
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();

Swing_MVC

23

Construction de larbre

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);
Swing_MVC

24

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);
}

Larbre change de racine


Swing_MVC

25

Un autre exemple : Un formulaire

public class LoginForm extends JFrame {


public LoginForm() {
super("LoginForm");
Container contents = getContentPane();
// contents.setLayout(new BorderLayout()); // par dfaut

contents.add( getLoginPanel(), BorderLayout.CENTER);


contents.add( getButtonPanel(), BorderLayout.SOUTH);
pack(); setVisible(true);
}
Swing_MVC

26

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;
}
Swing_MVC

27

Dmonstration
Un Arbre ?

Swing_MVC

28

Autres composants
suivre

Fentres de dialogues
JOptionPane

Apparence des objets graphiques


Apparence windows , Metal,
UIManager.setLookAndFeel

Swing_MVC

29

Une autre famille : JOptionPane

Swing_MVC

30

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"}, "Noix");
// response = ( "Amandes" | "Noisettes" | "Noix" | null)
}
}
Swing_MVC

31

Au choix

Mthode
showConfirmDialog
showInputDialog
showMessageDialog
showOptionDialog

Description
Pose une question oui/non/annuler.
Demande un choix (c.f. exemple prcdent).
Une indication.
Unification des 3 prcdents.

Lecture bloquante jusqu ce que lutilisateur

Swing_MVC

32

Les Apparences LookAndFeel


Choix de lapparence.
Metal (par dfaut)
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");

Windows
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");

Apparence Motif
UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");

Swing_MVC

33

Apparence Windows

Swing_MVC

34

Apparence Mtal (Par Dfaut)

Swing_MVC

35

Swing : o sont les patrons ?

Patron Composite
Construction dune IHM

Patron Stratgie
Disposition des objets graphiques

Swing_MVC

36

Swing_MVC

37

Le patron Composite, rappel

Structures de donnes rcursives


Un Composant est une feuille ou un composite
Un Composite est un Composant
Swing_MVC

38

Le patron Composite et lAPI graphique

Component

JLabel

Swing_MVC

JButton

Container

39

Le formulaire est une instance du composite !

Swing_MVC

src : Mastering JSF page 31

40

list() comme operation()


Mthode de la classe Component quelque soit larbre
Component loginForm = new LoginForm();
loginForm.list();
LoginForm[frame0,0,0,183x103,layout=java.awt.BorderLayout,title=LoginForm,resizable,normal,defaul
tCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,4,23,175x76,layout=javax.swin
g.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,mi
nimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
javax.swing.JRootPane[,4,23,175x76,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,align
mentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=]
javax.swing.JPanel[null.glassPane,0,0,175x76,hidden,layout=java.awt.FlowLayout,alignmentX=0.0,alig
nmentY=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]

Swing_MVC

41

Retour sur Loriginal

Mthode Operation()
Component c = une feuille ou un composite
C.Operation();

Notons laccs aux enfants depuis un nud composite, classe Component


Mthode getChild

Swing_MVC

42

Le patron Strategy

Context ctxt = new Context(new ConcreteStrategyB());


Le champ dinstance aStrategy est affect par largument du constructeur

Puis
ctxt.contextInterface();
Retournera un AlgorithmInterface() concret
Swing_MVC

43

Le patron Strategy et les layout

Container

BorderLayout

LayoutManager

FlowLayout

GridLayout

Exemple :
Container content = getContentPane();
content.setLayout(new BorderLayout());
Swing_MVC

44

Les images (encore un patron), en appart


Le chargement dune image peut-tre lent
Si cest synchrone alors lapplication attend

alors un chargement asynchrone simpose

Pour cela usage


Du paradigme Producteur/Consommateur
Du patron observateur
Une instance de la classe Image nest pas un tableau de pixels mais un
canal entre un producteur dimage et son consommateur
Limage est un observateur, notifie par le producteur

Swing_MVC

45

<<Interface>>
ImageProducer

<<Interface>>
Ima ge Consumer
se tDime nsions()
se tProp erties()
se tColorModel()
se tHints()
se tPixels()
se tPixels()
im ag eCo mplete()

0..*

addConsumer(ic : ImageConsumer) : void


isConsumer(ic : ImageConsumer) : boolean
removeConsumer(ic : ImageConsumer) : void
startProduction(ic : ImageConsumer) : void
requestTopDownLeftRightResend(ic
: ImageConsumer) : void
src

FilteredImageSource

MemoryImageSource

<<Interface>>
ImageObserver
imageUpdate(img : Image, infoflags : int, x : int, y : int, width : int, height : int) : boolean

Im age
Component

getWidth(observer : ImageObserver) : int


getHeight(observer : ImageObserver) : int
getSource() : ImageProducer
getGraphics() : Graphics
getProperty(name : String, observer : ImageObserver) : Object
getScaledInstance(width : int, height : int, hints : int) : Image
flush() : void

BufferedImage

Swing_MVC

46

Un exemple Aurores borales au Cnam ?


public class ImageDemo {
static public void main(String args[]) throws Exception {
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/images/logo_cnam.gif"));
m2=toolkit.getImage(new
URL("http://media.aftenposten.no/archive/00411/_1274097_jpg_411307h.jpg"));

}
public void paintComponent(Graphics g) {
Dimension d = getSize();
g.drawImage(m2,0,0,this);
g.drawImage(m1,0,0,this);
}
}}
Swing_MVC

47

Ragir aux clics : le formulaire dj vu

Associer une action au clic sur OK


lgitime

Patron observateur/observ
Les listeners

Swing_MVC

48

Patron observ/observateur-couteur( ou listener)


1) enregistrement auprs du bouton dun couteur
bouton.addActionListener(ActionListener al)
Plusieurs couteurs sont possibles

2) A chaque clic les couteurs sont notifis


al.actionPerformed(ActionEvent ae)

Lexemple du formulaire suit

Swing_MVC

49

le patron Observateur, loriginal

Swing_MVC

http://www.codeproject.com/gen/design/applyingpatterns/observer.gif
50

Ajout dun 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;
}
}

Swing_MVC

51

OkButton action !!!


class OkButtonAction implements ActionListener{
public void actionPerformed(ActionEvent ae){
// Vrification du nom et mot de passe
// par exemple
}
}
Diffrentes formes syntaxiques possibles
Classe interne et statique
Classe interne et membre
Classe anonyme
Swing_MVC

52

Action, Listeners et les autres, par convention


Un composant swing enregistre ses couteurs
addXXXXListener

Les couteurs implmentent


Linterface XXXXListener et sont des java.awt.event.EventListener
Cette interface dcrit une mthode acceptant en paramtre un XXXXEvent
Chaque couteur senregistre auprs du composant swing

A chaque changement dtat du composant swing


Les mthodes des couteurs pr-enregistrs sont excutes
Le paramtre XXXXEvent contient au moins la source de la notification

Swing_MVC

53

EventListener et ses descendants

Hritage au sens des interfaces


Swing_MVC

54

Des Adaptateurs adapter


Implmenter un XXXXListener peut tre fastidieux
Surtout si une seule mthode de linterface est concerne
Exemple : linterface 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 mthodes implmenter

Utile : il existe une classe XXXXAdapter qui implmente XXXXListener


Exemple la classe WindowAdapter

Swing_MVC

55

XXXXAdapter adapter
Exemple suite : WindowAdapter
Au clic dans la case de fermeture alors arrt brutal du programme
Pas daction pour les 6 autres mthodes.

Window w =
w.addWindowListener(
new WindowAdapter(){
public void windowClosing(WindowEvent event) {
System.exit(0);
}
});

Swing_MVC

56

Swing, un constat

Cest une premire prsentation


Des composants graphiques
Une gestion des vnements
Un look and feel indpendant

IHM alors MVC


Modle Vue Contrleur
Comment ?, quel dploiement ?, pourquoi faire ?

Swing_MVC

57

Interactivit, MVC
Linterface graphique
La vue

Interactions avec lutilisateur


Le contrle

Les donnes de lapplication


Le modle

A la recherche
dune adquation des donnes de lapplication et des vues
Paradigme MVC
Modle Vue Contrleur

Swing_MVC

58

MVC, doc de Sun

http://java.sun.com/blueprints/patterns/MVC-detailed.html
Un exemple
Swing_MVC

59

MVC un exemple : un nombre !


le modle : un nombre

50

37
Une vue
Une vue

Un contrle

une jauge

Dploiement ?
IHM ?
Contrle ?
Modle ?

Swing_MVC

37
Une JFrame
60

Dploiement ? Choix de classes

Discussion
Le modle :
La Vue :
Le Contrle :
Swing_MVC

la classe Nombre
Une JFrame, une jauge, un affichage, des boutons
Ractions aux actions de lutilisateur
61

Un dploiement possible, dmonstration


La classe Nombre est Observable
Elle hrite de java.util.Observable

Les Vues sont des observateurs


Elles implmentent java.util.Observer,
Peuvent tre des IHM, des Container swing,
Sans interface : des vues sans tre vues ?
Par exemple : un journal des vnements

Les Contrles grent les actions de lutilisateur


Elles implmentent les XXXXListener des composants swing
Une classe par action ?

Swing_MVC

62

Exemple un nombre, une vue, un contrle

public class MainNombreMVC{


public static void main(String[] args){

Nombre nombre = new Nombre(0,10); // le modle


Vue1 vue1 = new Vue1(nombre);
ControleVue1 controle1 = new ControleVue1(nombre, vue1);
}
}
Swing_MVC

63

Le modle
public 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()
Swing_MVC

64

La Vue est une JFrame et implmente Observer


public class Vue1 extends JFrame implements Observer{
private
private
private
private

JButton
JButton
JTextField
JSlider

plus;
moins;
valeur;
jauge;

public Vue1(Nombre nombre) {


super("Vue1 Nombre");

nombre.addObserver(this);
// Mise en place des composants graphiques

en quelques lignes ,
un arbre instance du composite
pack();
setVisible(true);
}
Swing_MVC

65

La Vue implmente java.util.Observer


@Override
public void update(Observable obs, Object arg){
if(obs instanceof Nombre){
Nombre n = (Nombre)obs;
this.valeur.setText(n.toString());
this.jauge.setValue(n.getValeur());
}
}

// accesseurs
public JButton getPlus(){return plus;}
public JButton getMoins(){return moins;}
}
Swing_MVC

66

Le Contrle implmente 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();
}
});
}
}
Swing_MVC

adquation actions de lutilisateur / oprations sur le modle


67

Dmonstration
Dmonstration
MVC pourquoi faire ?

Paradigme au-del de la maturit ?


Loriginal en 1978 http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html

Donner lillusion
lutilisateur de
manipuler les donnes
du modle

Swing_MVC

68

Une nouvelle vue, un nouveau contrle, critiques

public class MainNombreMVC{


public static void main(String[] args){
Nombre nombre = new Nombre(0,10); // le modle
Vue1 vue1 = new Vue1(nombre);
ControleVue1 controle1 = new ControleVue1(nombre, vue1);
Vue2 vue2 = new Vue2(nombre);
ControleVue2 controle2 = new ControleVue2(nombre, vue2);
}
}

lutilisateur peut maintenant modifier la valeur


ajout dun observateur auprs dun JTextField
soit jTextField.addActionListener

Swing_MVC

69

La classe Vue2, est un observateur


public class Vue2 extends JFrame implements Observer{
private JTextField
private JSlider

valeur;
jauge;

public Vue2(Nombre nombre) {


super("Vue2 Nombre");
nombre.addObserver(this);
Container content = getContentPane();
en quelques lignes
}
public void update(Observable obs, Object arg){
if(obs instanceof Nombre){ // instanceof prvention
Nombre n = (Nombre)obs;
this.valeur.setText(n.toString());
this.jauge.setValue(n.getValeur());
}
}
public JTextField getValeur(){return valeur;}}
Swing_MVC

70

Le Contrle2 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().getText());

ControleVue2.this.nombre.setValeur(valeur);
}catch(NumberFormatException nfe){
}
}
});
}
}

Une nouvelle vue engendre ici une nouvelle classe de contrle, critiques ?
Faire autrement ? mieux ?
Swing_MVC

71

Deux nombres 4 vues, 4 Contrles


public class MainNombreMVC{
public static void main(String[] args){
Nombre nombre = new Nombre(0,10); // le modle
Vue1 vue1 = new Vue1(nombre);
ControleVue1 controle1 = new ControleVue1(nombre, vue1);
Vue2 vue2 = new Vue2(nombre);
ControleVue2 controle2 = new ControleVue2(nombre, vue2);
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);
}
}
Dmonstration

Un dernier exemple : deux nombres 8 vues, 25 Contrles, non merci


Swing_MVC

72

Discussion / lexemple

Remarquons que : View Selection


Est absent de lexemple
Swing_MVC

73

Discussion sur limplmentation du Modle


public class Nombre
Le Modle est une classe
Cette classe hrite de java.util.Observable sur cet exemple

Ce modle peut devenir un composant logiciel


Un JavaBean
Peu de diffrences part quelques rgles dcritures
Ces rgles permettront une utilisation de ce composant par des outils,
Vers une meilleure rutilisation ?
Vers une industrie du composant logiciels ?
EJB ? Enterprise JavaBeans

Un nouveau langage au dessus de Java?


Swing_MVC

74

Observable/Observer la mode JavaBeans


Paquetage java.beans
Champs dinstance
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)
Swing_MVC

75

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 dfaut
Un getter et/ou un setter pour chaque variable dinstance
firePropertyChange au sein du setter

Simple nest-ce pas ?

La suite
Nombre devient Bean
La BeanBox, loutil dassemblage de Beans : un outil historique
Introspection systmatique
Swing_MVC

76

La classe Nombre devient Bean : NombreBean


public 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(this);
}
public void inc(){
if(valeur < VALEUR_MAX){
int old = valeur;
this.valeur++;
propertySupport.firePropertyChange("valeur",old,valeur);
}
}
public void addPropertyChangeListener(PropertyChangeListener l) {
propertySupport.addPropertyChangeListener(l);
}
// public int getValeur() et setValeur()

Swing_MVC

77

La Vue est lcoute de son Bean


public class Vue1Bean extends JFrame implements PropertyChangeListener{
private
private
private
private

JButton
JButton
JTextField
JSlider

plus;
moins;
valeur;
jauge;

public Vue1Bean(NombreBean nombre) {


super("Vue1 Nombre");
nombre.addPropertyChangeListener(this);
// Le dessin ici
}
@Override
public void propertyChange(PropertyChangeEvent evt){
assert evt.getPropertyName().equals("valeur");
this.valeur.setText(evt.getNewValue().toString());
this.jauge.setValue((Integer)evt.getNewValue());
}

Les contrles ne changent pas, le MVC reste en ltat


Swing_MVC

78

NombreBean intgre la BeanBox

setValeur
getValeur

Ajout par loutil BeanBox dun listener (EventMonitor)


chaque changement de valeur de valeur
dmonstration pour lhistoire cest un outil du sicle dernier
Usage de lintrospection
Swing_MVC

79

Dmonstration
Deux instances de NombreBean
Un jongleur

La premire instance de NombreBean


loccurrence dun changement de valeur demande au jongleur darrter de
jongler

La seconde instance de NombreBean


loccurrence dun changement de valeur demande au jongleur de jongler

Swing_MVC

80

Le squelette dun source de Bean,


gnr par netBeans explication
public class SimpleBean extends JLabel implements Serializable {
public SimpleBean() {
setText( "Hello world!" );
propertySupport = new PropertyChangeSupport(this);
}
public static final String PROP_SAMPLE_PROPERTY = "sampleProperty";
private String sampleProperty;
private PropertyChangeSupport propertySupport;
// recherche de cette mthode par un outil, par introspection
public String getSampleProperty() { return sampleProperty;}

// recherche de cette mthode par un outil, par introspection


public void setSampleProperty(String value) {
String oldValue = sampleProperty;
sampleProperty = value;
propertySupport.firePropertyChange(PROP_SAMPLE_PROPERTY,
oldValue, sampleProperty);
}

// recherche de cette mthode par un outil, par introspection


public void addPropertyChangeListener(PropertyChangeListener listener) {
propertySupport.addPropertyChangeListener(listener);
}}
Swing_MVC

81

Usage de lintrospection
Affecter la proprit dun bean
Object obj
String name
int value

une instance
le nom de la proprit
la nouvelle valeur

public void setProperty(Object obj, String name, int value) {


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 });

Swing_MVC

82

MVC un autre schma, encore !, tjs daccord ?

src : Mastering JSF page 6


Swing_MVC

83

Conclusion ? discussion

MVC au niveau dune application


Et Il y a aussi un MVC au niveau de chaque composant swing
Swing_MVC

84

Conclusion, discussion
MVC
Mature

La suite

MVC et composant swing


Certains composants proposent de changer le modle et lIHM

Swing_MVC

85

Un Composant Swing et MVC


Par exemple
JTextField
Une zone de texte (classe JTextComponent)

Le Modle
Le texte (classe PlainDocument)

Linterface Utilisateur
Un rectangle (classe BasicTextFieldUI )

En standard
JTextField field = new JTextField();

Avec un autre modle


JTextField field = new JTextField (new unAutreModleDeDocument());

Avec une autre interface utilisateur (vue)


field.setUI(new uneAutreInterface());
Swing_MVC

86

Un exemple, avec dmo possible


Le nouveau JTextField ne peut contenir que des majuscules !
Une contrainte sur une entre du formulaire
Un nouveau modle, ici une sous-classe de Document
this.userIdField = new JTextField(new UnAutreModleDeTexte(), "", 10);

public class UnAutreModleDeTexte extends PlainDocument {


public void insertString(int offs, String str, AttributeSet 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);
}
}

Swing_MVC

87

Donc nous avons MVC et SMA


SMA : Separable Model Architecture

ou bien

Swing_MVC

88

SMA

Envoi dun
vnement lors dun
changement dtat

Lecture de ltat du modle

Swing_MVC

89

Swing_MVC

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
90

Model et Notification
Model
ListModel

Listener
ListDataListener

Event
ListDataEvent

ListSelectionModel

ListSelectionListener

ListSelectionEvent

ComboBoxModel

ListDataListener

ListDataEvent

TreeModel

TreeModelListener

TreeModelEvent

TreeSelectionModel

TreeSelectionListener

TreeSelectionEvent

TableModel

TableModelListener

TableModelEvent

TableColumnModel

TableColumnModelListener

TableColumnModelEvent

Document

DocumentListener

DocumentEvent

Document

UndoableEditListener

UndoableEditEvent

Swing_MVC

91

Jlist and ListModelexemple fourni.. suivre

Swing_MVC

92

JC o m p o n e n t

C o m p o n e n tU I
# ui

JL ist
JL ist()
se tC e llRe nd e re r()
se tM o d e l()
- da taM od el

L istU I

# list

B a sicL istUI

<<Inte rfa ce >>


L istM o d e l
# listD a ta L iste ne r

g etS ize ()
g etE le me ntAt( )
a dd ListD a taL istene r( )
r em oveL istD ata Liste ner ()

<<Inte rfa ce >>


L istD a ta L iste ne r
inte rva lA d d e d (e : L istD a ta E ve nt) : void
inte rva lRe m o ve d (e : L istD a ta E ve nt) : vo id
co nte ntsC ha ng e d (e : L istD a ta E ve nt) : vo id
0 ..*

A b stra ctL istM o d e l


L istD a ta E ve nt
a d d L istD a ta L iste ner(l : L istD a ta L iste ne r) : vo id
re m o ve L istD a ta L iste ne r(l : L istD a ta L iste ne r) : vo id
fire C o nte ntsC ha ng ed (so urce : Ob je ct, ind e x0 : int, ind e x1 : int) : void
fire Inte rva lA d d e d (source : Ob je ct, ind e x0 : int, ind e x1 : int) : vo id
fire Inte rva lRe m o ve d(so urce : Ob je ct, ind e x0 : int, ind e x1 : int) : vo id
g e tL iste ne rs(liste nerTyp e : C la ss) : E ve ntL iste ne r[]
Swing_MVC

g e tTyp e ()
g e tInd e x0 ()
g e tInd e x1 ()
L istD a ta E ve nt()

93

<<Interface>>
ListD ataListener
JC o m po ne nt
<<Interface>>
T ab le Mo de l
getRowC ount()
getC olum nC ount()
getC olum nNam e()
getC olum nC lass()
isC ellE ditable()
getV alueA t()
setV alueA t()
addTableM odelListener()
rem oveTableM odelListener()

#ui
C o m po ne ntU I

#dataM odel

JTable

T ableU I

#table

<<Interface>>
TableM odelListener

B asicTableUI

ta bleC ha nged(e : TableM odelE vent) : void


0..*
A bstractT ableM odel
getC olum nNam e(colum n : int) : S tring
findC olum n(colum nNam e : S tring) : int
getC olum nC lass(colum nIndex : int) : C lass
isC ellE ditable(rowIndex : int, colum nIndex : int) : boolean
setV alueA t(aV alue : Object, rowIndex : int, colum nIndex : int) : void
addTableM odelListener(l : TableM odelListener) : void
rem oveTableM odelListener(l : TableM odelListener) : void
fireTableD ataC hanged() : void
fireTableS tructureC hanged() : void
fireTableRowsInserted(firstRow : int, lastRow : int) : void
fireTableRowsUpdated(firstRow : int, lastRow : int) : void
fireTableRowsD eleted(firstRow : int, lastRow : int) : void
fireTableC ellUpdated(row : int, colum n : int) : void
fireTableC hanged(e : TableM odelE vent) : void
getListeners(listenerType : C lass) : E ventListener[]
Swing_MVC

TableM odelE vent


D E LE TE : int = - 1
INS E RT : int = 1
UP D A TE : int = 0
getC olum n()
getF irstRow()
getLastRow()
getType()

94

Pause la suite
MVC Web
JSF

Framework pour applications web


MVC web
Configuration en fichier xml
Mise en place dun JavaBean adaptateur si ncessaire
Critiques

JSF-2

Swing_MVC

Ajax
@Annotations
Appel de JavaBean avec source ou non
Critiques
95