Title: Interfaces Graphiques
1Interfaces Graphiques
- Pascal Molli
- Maître de Conférence NANCY1
- www.loria.fr/molli
2Faire une interface graphique...
- Comment construire un écran graphique ?
- Comment gérer les événements ?
- Comment maintenir le mapping objets applicatifs /
objets graphiques ?
3Modèle de programmation événementiel !
- Programme principal d une appli graphique
- Définition des écrans
- Construire un arbre de composants graphiques.
- Mettre en place les callbacks
- on event do action
- Lancer la boucle d événement (boucle infinie)
4Définition des écrans !
- Un écran graphique 1 arbre de composants
graphiques - Les feuilles des composants atomiques (button,
List, TextField) - Les nuds des conteneurs (des zones pour mettre
des composants atomiques) - La racine La fenêtre
- Une application plein d écrans graphiques
5Diagramme de classe (partiel) d une lib
graphique !
Une classe abstraite!
Les composants atomiques
Les composants composites !
Pas de nouvelles fenêtres
6Instancions Une Todo list...
TextField
List
Button
7La TodoList !
Frame
Panel
Panel
8Donc 1 arbre !
9Comment placer les objets ?
- Pas de placement absolu i.e. pas de button1 en
x3, y4 - Utilisation d algorithmes de placement
- Placement en  matriceÂ
- Placement  à la queue leu leu -D
- Les algorithmes de placements sont associés au
nuds !
10Container et layout...
11Border Layout ...
Prend une zone et la découpe en 5 zones...
12Grid Layout
Découpe une zone en une matrice !
13Instanciation...
14Instanciation...
Frameborder
Buttons
Text Field
List
Panelborder
Panelgrid
15Mise en place de l écran...
16Gestion des événements...
- Modèle par délégation
- propager les objets événements d une source
(Composant graphique) - Vers un  écouteur d événement une classe
 sous-classe  de actionListener - Un composant graphique est donc relié à une liste
 d actionListenerÂ
17La statique...
18La dynamique...
19Click !
20Du code ??
package task class Main public static
void main(String args) TaskForm tfnew
TaskForm() tf.pack() tf.show()
21package task import java.awt. import
java.awt.event. class TaskForm extends Frame
implements ActionListener private TextField
tfnew TextField() private List lnew
List() private Button addnew
Button("add") private Button removenew
Button("remove") TaskForm()
this.setLayout(new BorderLayout()) Panel
centernew Panel() Panel eastnew
Panel() this.add("Center",center) this.add("Ea
st",east) center.setLayout(new
BorderLayout()) center.add("North",tf) center.
add("Center",l) east.setLayout(new
GridLayout(0,1)) east.add(add) east.add(remove
) add.addActionListener(this) remove.addActio
nListener(this) lt.gt
22ltgt public void actionPerformed(ActionEvent e)
if (e.getSource()add)
l.add(tf.getText()) if (e.getSource()remov
e) l.remove(l.getSelectedItem())
23Résumons nous...
- Créer des écrans
- faire des arbres de  ComponentÂ
- Gérer les évenements
- Modèle pas délégation
- Déclaration des propagations
- addActionListener
- écouter les événements
- Sous-classer ActionListener et redéfinir la
méthode ActionPerformed(ActionEvent e)
242D Graphics
25Painting
- A graphical component is an abstract object with
a position, a size, able to receive events and
THAT CAN BE DRAWED ! - Extends a Jcomponent (Jpanel)
- Override the paintComponent(Graphics g) method
26(No Transcript)
27(No Transcript)
28Simple Demo
29Coordinate
30Painting process in Swing
- paint() invokes paintComponent() .
- If the ui property is non-null, paintComponent()
invokes ui.update(). - If the component's opaque property is true,
ui.udpate() fills the component's background with
the background color and invokes ui.paint(). - ui.paint() renders the content of the component
31Swing and Java2D
- A Library for extending capabilities of
 graphics - A uniform rendering model for display devices and
printers - A wide range of geometric primitives,
- Mechanisms for performing hit detection
- A compositing model
- Enhanced color support
- Support for printing
32(No Transcript)
33Using Java2D
- public void paintComponent(Graphics g)
Graphics2D g2 (Graphics2D) g ... -
342D and Interaction
352D and events
36(No Transcript)
37Images
38Source
39- Loading a picture may be slow
- If loading is synchronous, programs is blocked...
- Idea Separates the Image Objects from the
pixels that composes the Image. Goal ?
Asynchronous loading of images... - An Image Object is not a pixel array but a pipe
between a pixel source and a pixel consumer.
40Producer/consumer/Observer Paradigm
- getImage() call returns immediately an object of
the class Image'' a pixel pipe. - On one side there is the pixel consumer just a
class that implements the ImageObserver Class - On the other side, the pixel producer just a
class that produce pixels
41(No Transcript)
42Buffered
43(No Transcript)
44Using Layered Pane
45Bon et maintenant
- Petit problème
- Si les données à afficher viennent des objets de
mon application ?? - Comment maintenir le mapping entre les données
affichées et les données de mon application ?? - Utilisation du MVC Model/View/Controller...
46The philosophy behind the Java event model
- Model-View-Controller
- Comes from Smalltalk
- Separate
- application Model
- user display View
- controlling object Controller
47Model-View-Contoler (MVC)
- The model contains the core functionality and
data? - Views display information to the user.
- Controllers handle user input.
- A change propagation mechanism ensure consistency
between user interface and the model.
48(No Transcript)
49MVC Structure
50MVC Structure
51MVC Structure
52 MVC Known Uses
- Smalltalk
- MFC
- ET application Framework
53MVC benefits
- Multiple views of the same model
- Synchronized views change propagation
- Pluggable views and controllers
- Exchangeability of look and feel
- Framework potential
54MVC Liabilities
- Increased complexity
- Potential for excessive number of updates
- Intimate connection between view and controller
- Close coupling of views and controllers to a
model - Inefficiency of data access in view
- Inevitability of change to view and controller
when porting - Difficulty of using MVC with modern
user-interface tools
55MVC
- Modèle objet applicatif
- Vue objets graphiques observant le modèle
(output) - Contrôleur objets scannant les  inputs et
provoquant les changements du modèle
56(No Transcript)
57(No Transcript)
58(No Transcript)
59 class Controller extends JPanel implements
Observer private JButton jrepos new
JButton("Repos") private JButton jarme new
JButton("Enlever Arme") private JButton
jarmure new JButton("Enlever Armure") Controll
er() this.setLayout(new GridLayout(0,2))
Mauhly.this.addObserver(this)
jrepos.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent
e) Mauhly.this.reposer() )
jarme.addActionListener(new
ActionListener() public void
actionPerformed(ActionEvent e) Mauhly.this.un
setArme() )
jarmure.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent
e) Mauhly.this.unsetArmure()
) this.add(jrepos)
this.add(jarme) this.add(jarmure) publ
ic void update(Observable o, Object arg)
jarme.setEnabled(Mauhly.this.arme!null)
jarmure.setEnabled(Mauhly.this.armure!null)
Class Maulhy extends Observable class
Controller extends JPanel implements Observer
private JButton jrepos new JButton("Repos")
private JButton jarme new JButton("Enlever
Arme") private JButton jarmure new
JButton("Enlever Armure") Controller()
this.setLayout(new GridLayout(0,2))
Mauhly.this.addObserver(this)
jrepos.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent
e) Mauhly.this.reposer() )
jarme.addActionListener(new
ActionListener() public void
actionPerformed(ActionEvent e) Mauhly.this.un
setArme() )
jarmure.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent
e) Mauhly.this.unsetArmure()
) this.add(jrepos)
this.add(jarme) this.add(jarmure) publ
ic void update(Observable o, Object arg)
jarme.setEnabled(Mauhly.this.arme!null)
jarmure.setEnabled(Mauhly.this.armure!null)
60(No Transcript)
61(No Transcript)
62SWING
- Swing vs AWT vs SWT
- Lightweight Component
- Java rendering
- Pluggable look and feel
- Separable model archi (MVC)
- Bean Compliant
- Clipboard and DND support.
63Consequences
- More complex widget
- Jtree, Jtable, Internal Frames
- No more dependent of native capabilities of host
systems - Allow more efficient rendering
64Jcomponent
- Jcomponent subclass of container with
- Pluggable look and feel (plaf)
- Keystroke Handling
- Support for tooltips
- Accessibility
- Support for properties..
- Double buffering for painting
65(No Transcript)
66From MVC to SMA
- SMA Separable Model Archi
67Send Event for change propag
Read state of model
68(No Transcript)
69Model Change Notification
70Jlist and ListModel
71(No Transcript)
72- public abstract class AbstractListModel
implements ListModel,Serializable - protected EventListenerList listenerList
new EventListenerList() - public void addListDataListener(ListDataListen
er l) - listenerList.add(ListDataListener.class, l)
-
- public void removeListDataListener(ListDataLis
tener l) - listenerList.remove(ListDataListener.class, l)
-
- protected void fireContentsChanged(Object source,
int index0, int index1) - Object listeners listenerList.getListenerList
() - ListDataEvent e null
- for (int i listeners.length - 2 i gt 0 i -
2) - if (listenersi ListDataListener.class)
- if (e null)
- e new ListDataEvent(source,
ListDataEvent.CONTENTS_CHANGED, index0,index1) -
- ((ListDataListener)listenersi1).contentsChange
d(e) -
-
73(No Transcript)
74(No Transcript)
75(No Transcript)
76(No Transcript)
77(No Transcript)
78(No Transcript)
79class SacRoot extends Sac implements TreeModel
private Vector vnew Vector() SacRoot()
public void addTreeModelListener(Tr
eeModelListener l) v.addElement(l)
public Object getChild(Object parent, int
index) if (((Equipement)parent).isLeaf()
) return null else
return ((Sac)parent).getEquip().get(index)
public int getChildCount(Object
parent) if (((Equipement)parent).isLeaf(
)) return 0 else
return ((Sac)parent).getEquip().size()
public int getIndexOfChild(Object parent,
Object child) if (((Equipement)parent).i
sLeaf()) return 0 else return
((Sac)parent).getEquip().indexOf(child)
public Object getRoot() return
this public boolean isLeaf(Object node)
return ((Equipement)node).isLeaf()
public void removeTreeModelListener(TreeMode
lListener l) v.removeElement(l)
public void valueForPathChanged(TreePath path,
Object newValue) public void reload()
System.out.println("yo")
TreeModelEvent eventnew TreeModelEvent(this,new
TreePath(this)) for (Enumeration e
v.elements() e.hasMoreElements() )
TreeModelListener l(TreeModelListener)e.nextEle
ment() l.treeStructureChanged(event)
80TreeModel an Adapter Pattern
Based on inheritance
81TreeModel (object composition)
82(No Transcript)
83Adapter participants
- Target (TreeModel)
- defines the domain-specific interface that Client
uses. - Client (JTree)
- collaborates with objects conforming to the
Target interface. - Adaptee (Component)
- defines an existing interface that needs
adapting. - Adapter (What you have to write !)
- adapts the interface of Adaptee to the Target
interface.
84(No Transcript)
85(No Transcript)
86class GlyphRoot extends GlyphContainer implements
TreeModel private Vector vnew Vector()
GlyphRoot() public void
addTreeModelListener(TreeModelListener l)
v.addElement(l) public void
removeTreeModelListener(TreeModelListener l)
v.removeElement(l) public Object
getChild(Object parent, int index) return
((Glyph)parent).getChild(index) public
int getChildCount(Object parent) return
((Glyph)parent).getChildCount() public
int getIndexOfChild(Object parent, Object child)
return ((Glyph)parent).getIndexOfChild(child)
public Object getRoot() return
this .
87class GlyphRoot extends GlyphContainer implements
TreeModel private Object getPath(Glyph g)
Vector vnew Vector() Glyph
currentg while (current!this)
v.add(0,current) currentg.getParent()
v.add(0,this) return v.toArray() public
void fireTreeNodesInserted(Glyph g)
TreeModelEvent eventnew TreeModelEvent(this,
getPath(g.getParent()), new int
getIndexOfChild(g.getParent(),g), new
Object g ) for (Enumeration e
v.elements() e.hasMoreElements() )
TreeModelListener l(TreeModelListener)e.nextEleme
nt() l.treeNodesInserted(event)
public void fireTreeNodesRemoved(Glyph g)
TreeModelEvent eventnew TreeModelEvent(this,
getPath(g.getParent()), new int
getIndexOfChild(g.getParent(),g), new
Object g ) for (Enumeration e
v.elements() e.hasMoreElements() )
TreeModelListener l(TreeModelListener)e.nextEleme
nt() l.treeNodesRemoved(event)
88class GlyphContainer extends Glyph
protected Vector vnew Vector() public
GlyphContainer( ) int getChildCount()
return v.size() Object
getChild(int i) return v.elementAt(i)
public int getIndexOfChild(Object child)
return v.indexOf(child) boolean
isLeaf() return false public void
add(Glyph g) g.setParent(this) v.addElement(g
) this.getGlyphRoot().fireTreeNodesInserted(g)
public void remove(Glyph g)
this.getGlyphRoot().fireTreeNodesRemoved(g) v
.remove(g) g.setParent(null)
89(No Transcript)
90(No Transcript)
91The PLAF !
JAVA LF
Motif LF
Windows LF
- Applying the abstract factory pattern
92(No Transcript)
93(No Transcript)
94(No Transcript)
95(No Transcript)
96(No Transcript)
97(No Transcript)
98- AbstractFactory (WidgetFactory)
- declares an interface for operations that create
abstract product objects. - ConcreteFactory (MotifWidgetFactory)
- implements the operations to create concrete
product objects. - AbstractProduct (Window, ScrollBar)
- declares an interface for a type of product
object. - ConcreteProduct (MotifWindow,MotifScrollBar)
- defines a product object to be created by the
corresponding concrete factory. - implements the AbstractProduct interface.
- Client
- uses only interfaces declared by AbstractFactory
and AbstractProduct classes.
99Mapping sur SWING
- Abstract factory LookAndFeel
- Choix de la fabrique concrête UIManager
- Produit Abstrait ComponentUI et ses
sous-classes (UIDelegate) - Produit concrêt BasicListUI,MetalListUI
100Bridge Pattern
101(No Transcript)
102Modèle par composant
Source
- Définition d un composant
- Module logiciel autonome (self contained) et
réutilisable - Peut-être composé visuellement (donc
dynamiquement !) pour former une application
(application builder). - Beans, EJB, Corba Component.
103La philosophie des composants
Source IBM online course
104Composants
- Un composant
- des inputs/outputs déclarés
- pour établir des connexions
- des propriétés déclarées
- pour configurer le composant
- pour l écran voltage, taux de rafraichissement
- pour l ordinateur la séquence de boot, avec ou
sans passwd - Utiliser des composants
- Les connecter et les configurer
105Composant JavaBeans...
- Bean classe conventions d écriture
- Inputméthodes publiques
- Propriétésvariables d instances
accesseurs/modificateur - Outputévénements émis
- Mais ATTENTION
- on connecte et on configure des INSTANCES!!
- Les instances sont créées sur un BeanContainer
(modèle par composition)
106Composant Bean
- Le BeanContainer doit être capable d interroger
les INSTANCES pour - Découvrir les propriétés qui peuvent être
manipulées - Comment elles doivent être manipulées
- Découvrir les événements qui peuvent être émis
- Utilisation de l introspection ! La classe class
!!
107Composant Bean !
- Pour aider le BeanContainer, on prend les
conventions d  écriture suivantes - Constructeur de la classe sans paramètres
- Set/Get Methodes pour les propriétés
- Add/Remove methodes pour les événements
108Exemple Alarm Bean
- Un timer
- Propriétés durée du time-out
- private int timeout30
- input
- public void start(),
- public void stop()
- output
- public void addAlarmListener (AlarmListener
listener) ... - public void removeAlarmListener (AlarmListener
listener) ...
109Alarm Bean...
Source Pas de moi mais je sais plus -D
public class AlarmBean implements Runnable,
Serializable protected int timeout 1000
public AlarmBean () public void setTimeout
(int t) timeout t public int
getTimeout () return timeout
transient protected Thread alarm public
synchronized void start () ... public
synchronized void stop () ... public void run
() ... protected Vector listeners new
Vector () public void addAlarmListener
(AlarmListener listener) listeners.addElemen
t (listener) public void
removeAlarmListener (AlarmListener listener)
listeners.removeElement (listener)
protected void dispatchAlarmCall ()
AlarmEvent event new AlarmEvent (this)
Vector listeners (Vector) this.listeners.clone
() for (int i 0 i lt listeners.size ()
i) ((AlarmListener) listeners.elementAt
(i)).alarmCalled(event)
110Alarm Bean et Juggler Bean...
111Composant Bean
- Quand l alarme est activée
- il faut appeler juggler.stop()
- l application builder appelle
- alarm.addAlarmListener(juggler)
- et génère un adapteur qui implémente
AlarmListener et dans alarmCalled() appelle
juggler.stop(). - L adapteur est généré, compilé et chargé pendant
l exécution de l application builder...
112(No Transcript)
113(No Transcript)
114(No Transcript)
115(No Transcript)
116Layout Editing
117(No Transcript)
118Bean Palette
119Output de tout ça...
Source IBM online course
- Soit une application Java
- Soit une applet Java
- Soit un nouveau JavaBean qui n est lui-même
qu une composition de Bean primitifs - Modèle par composition
120Composant Bean
- Un bean n est pas forcément un composant visuel
il remplit une fonctionalité (input/output/propr
iétés) - Il peut tout à fait accéder à un objet distant
(RMI, CORBA), se connecter à un base de données,
ou attacher une queue JMS. - Mais pas de de gestion automatique de la
répartition...
121(No Transcript)
122(No Transcript)