Title: Dessin%20Java%20et%20Java%202D
1Dessin Java et Java 2D
- Java 2D et Swing
- Graphics
- repaint(), et en Swing
- Composants de base
- Chaîne de traitement
- Les formes (Shape)
- Les courbes, les aires
- Transformations affines
22D et Swing deux avantages
- Pour les composants AWT et Swing
- Pour laffichage Graphics et Graphics2D
Concepts nouveaux Shape, Transformations, Path
Affichage de base Texte, formes
géométriques simples
Concepts nouveaux affichage sophistiqué
Affichage sophistiqué double buffering
par défaut, calcul de la zone de rafraîchissement
3Le dessin de base
- Les outils de dessin sont assez rudimentaires
- des méthodes draw() et fill() pour lignes,
rectangles, ovales, polygone - choix de deux modes de dessin direct ou xor
- une zone de découpe (clipping) rectangulaire.
- Java 2 propose des possibilités très
sophistiquées - des méthods draw(Shape) et fill(Shape)
- Choix des 8 modes de dessin
- des zones de découpe arbitraires (en principe)
- des transformations géométriques complexes
- En Swing, le double buffering est automatique
par défaut.
4Contexte graphique
- L'outil de dessin est le contexte graphique,
objet de la classe Graphics. Il encapsule
l'information nécessaire, sous forme d'état
graphique.Celui-ci comporte - la zone de dessin (le composant), pour les
méthodes draw() et fill() - une éventuelle translation d'origine
- le rectangle de découpe (clipping)
- la couleur courante
- la fonte courante
- l'opération de dessin (simple ou xor)
- la couleur du xor, s'il y a lieu.
- Chaque composant peut accéder implicitement et
explicitement à un contexte graphique.
5Obtenir un contexte graphique
- On obtient un contexte graphique
- implicitement, dans une méthode paint() ou
update() AWT construit un contexte graphique
passé en paramètre, - explicitement, dans un composant ou dans une
image, par getGraphics(), - explicitement encore, en copiant un objet
Graphics existant. - Un contexte graphique utilise des ressources
systèmes. L'acquisition explicite doit être
accompagnée, in fine, par une libération
explicite au moyen de dispose(). - L'acquisition explicite d'un contexte graphique
est - dit-on - signe d'une programmation
maladroite.
6Un exemple
public class BonjourGribouille extends Applet
int xd, yd public void init()
addMouseListener(new Appuyeur())
addMouseMotionListener(new Dragueur())
class Appuyeur extends MouseAdapter public
void mousePressed(MouseEvent e) xd
e.getX() yd e.getY() class
Dragueur extends MouseMotionAdapter public
void mouseDragged(MouseEvent e) int x
e.getX(), y e.getY() Graphics g
getGraphics() g.drawLine(xd, yd, x, y)
xd x yd y g.dispose()
- Accès explicite à un contexte graphique.
- A chaque getGraphics(), un nouveau contexte est
fourni, ne connaissant rien du précédent.
7Sans appel explicite AWT seulement
- Fait appel à la triplette magique
- repaint
- update
- paint
- repaint() demande un rafraîchissement. Appelle
update(), en lui fournissant un contexte
graphique. - update() par défaut efface le dessin et appelle
paint(). - paint() par défaut ne fait rien.
- Ici
- repaint() appelle update()
- update() n'efface pas
- paint() trace la ligne.
public class BonjourGribouille2 extends Applet
int xd, yd, x, y public void init()
idem public void update(Graphics g)
paint(g) public void paint(Graphics g)
g.drawLine(xd, yd, x, y) xd x yd y
class Appuyeur extends MouseAdapter
public void mousePressed(MouseEvent e) xd
e.getX() yd e.getY() class
Dragueur extends MouseMotionAdapter public
void mouseDragged(MouseEvent e) x
e.getX() y e.getY() repaint()
8repaint()
Code simplifié de Component.java public void
Component.update(Graphics g)
g.setColor(getBackground()) g.fillRect(0,0,
width, height) g.setColor(getForeGround()) pai
nt(g) public void Component.paint(Graphics g)
- C'est la méthode par excellence pour rafraîchir
un affichage !
- repaint()poste un appel à update(). Plusieurs
appels peuvent être groupés. - update() effectue les opérations suivantes
- efface le composant en le remplissant avec la
couleur de fond - définit la couleur du contexte à la couleur de
dessin - appelle paint().
- paint() ne fait rien par défaut.
- repaint() est appelé automatiquement à la
retaille d'une fenêtre. - Pour dessiner, on redéfinit paint() ou update()
(ou les deux).
9repaint() en Swing
Code simplifié de ComponentUI.java public void
update(Graphics g, JComponent c) if
(c.isOpaque()) g.setColor(c.getBackground
()) g.fillRect(0,0, c.getWidth(),
c.getHeight()) paint(g, c)
- Reste la méthode par excellence pour rafraîchir
un affichage !
- repaint()poste un appel à update(). Plusieurs
appels peuvent être groupés. - update() appelle paint().
- paint() appelle successivement
- paintComponent() pour le dessin (le paint() en
AWT) - paintBorder()
- paintChildren().
- paintComponent() par défaut appelle
ComponentUI.update() qui efface et redessine le
fond si le composant est opaque (JPanel lest par
défaut). - Pour dessiner, on redéfinit paintComponent() et
il est utile dappeler super.paintComponent().
10Lignes, rectangles, ovales
- Le contour est dessiné par draw, l'intérieur est
rempli par fill. - Tracer une ligne, une ovale, un rectangle est
sans surprise. - L'interaction draw et fill est usuelle si l'on
veut voir le contour, il faut le tracer après.
11Polygônes
- Un polygône est une ligne polygonale fermée,
donnée par la suite de ses points. Les premier et
dernier points sont joints. - Deux constructeurs, et possibilité d'ajouter un
point. - Remplissage selon la "even-odd rule".
Constructeurs Polygon() Polygon(int xp, int
yp, int np) Données npoints xpoints ypoints Méth
odes addPoint(int x, int y) contains(Point
p) contains(int x, int y) getBounds() translate(in
t dx, int dy)
12Exemple
public void paint(Graphics g) int largeur
getSize().width int hauteur
getSize().height int dl largeur/2, dh
hauteur/2 int polx 0, dl, largeur,
dl int poly dh, 0, dh, hauteur
Polygon pol new Polygon(polx,poly,4)
g.setColor(Color.black) g.fillRect(0,0,largeur,
hauteur) g.setColor( Color.yellow)
g.fillPolygon(pol) g.setColor( Color.red)
g.fillRect(dl/2, dh/2, dl,dh) g.setColor(
Color.green) g.fillOval(dl/2, dh/2, dl,dh)
g.setColor( Color.blue) g.fillArc(dl/2, dh/2,
dl, dh, th, del)
public class Losange extends Applet int th
45, del 45 public void init()
addMouseListener(new MouseAdapter()
public void mousePressed(MouseEvent e)
th (th 10)360 repaint()
) public void paint(Graphics g) ...
13Et en Swing
class Dessin extends JPanel int theta 45,
del 45 public void paintComponent(Graphics g)
int largeur getSize().width int
hauteur getSize().height int dl
largeur/2, dh hauteur/2 int polx 0,
dl, largeur, dl int poly dh, 0, dh,
hauteur Polygon pol new
Polygon(polx,poly,4) g.setColor(Color.bla
ck) g.fillRect(0,0,largeur,hauteur)
g.setColor( Color.yellow) g.fillPolygon(pol)
g.setColor( Color.red) g.fillRect(dl/2,
dh/2, dl,dh) g.setColor( Color.green)
g.fillOval(dl/2, dh/2, dl,dh) g.setColor(
Color.blue) g.fillArc(dl/2, dh/2, dl,
dh,theta, del) ...
public class Losange extends JApplet public
void init() setContentPane(new Dessin())
... public Dessin() addMouseListener( new
MouseAdapter() public void
mousePressed(MouseEvent e) theta
(theta 10)360 repaint()
)
14Chaîne de traitement 2D
- Le processus de traitement est en plusieurs
étapes - déterminer ce qui doit être affiché (formes,
textes, images) - appliquer les transformations géométriques et le
clipping - déterminer la couleur
- combiner avec ce qui se trouve sur la surface
- Pour chacune de ces étapes, des multiples
possibilités existent.
Primitives graphiques
Opérations de rendu
Affichage
Formes Textes Images
Transformations Clipping Composition
Ecran Imprimante
15Détails
- On obtient un objet Graphics2D par conversion
- On améliore laffichage par antialiasing etc
- On choisit loutil de dessin au trait (contours)
public void paintComponent(Graphics g)
Graphics2D g2 (Graphics2D) g ...
RenderingHints hints ... g2.setRenderingHints(h
ints)
Stroke stroke ... g2.setStroke(stroke)
16Détails (suite)
- On choisit loutil de remplissage (couleur,
dégradé, motif) - On définit la forme de découpage
- On définit une transformation géométrique entre
lespace utilisateur et espace décran
Paint paint ... g2.setPaint(paint)
Shape clip ... g2.setClip(clip)
AffineTransfrom at ... g2.transform(at)
17Détails (fin)
- On ompose le dessin résultant avec le dessin
existant - On définit la forme à dessiner
- On laffiche
Composite composite ... g2.setComposite(composi
te)
Shape dessin ...
g2.fill(dessin) g2.draw(dessin)
18Les formes (1)
- Dans le paquetage java.awt.geom
- Mais Polygon inchangé
- La classe Point2D nest pas une forme
- un point nest pastracé
Polygon
RectangularShape
Float
Line2D
Double
Shape
Area
Float
CubicCurve2D
Double
QuadCurve2D
GeneralPath
Float
Point2D
Double
Point
19Les formes (2)
- RectangularShape est la classe abstraite de base
des formes qui sont décrites par un rectangle
Float
Arc2D
Double
Float
Line2D
Double
RectangularShape
Float
Ellipse2D
Double
Float
RoundRectangle2D
Double
Rectangle
20Usage avec Graphics2D
- La classe Graphics2D est une classe dérivée de
Graphics - La méthode JComponent.paintComponent(Graphics g)
reçoit en fait un Graphics2D.De même pour
paint(). - On convertit g par
- Graphics2D g2 (Graphics2D) g
- On utilise des méthodes
- fill(Shape s)
- draw(Shape s)
- Exemple
g2.fill(new Rectangle2D.Double(x, y, 100, 100))
21Traits
- Les traits se dessinent avec une plume de la
linterface Stroke, implémentée par BasicStroke. - Les attributs sont
- lépaisseur (width)
- fins de traits (end caps)
- CAP_BUTT, CAP_ROUND, CAP_SQUARE
- lien entre traits (join caps)
- JOIN_BEVEL, JOIN_MITER, JOIN_ROUND
- pointillé (dash)
- Par défaut
- trait continue dépaisseur 1, CAP_SQUARE,
JOIN_MITER, miter limit 10
g2.setStroke(new BasicStroke(14,
BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL))
22Détails
- Cet exemple contient lillustration de plusieurs
aspects
public void paintComponent(Graphics g)
Graphics2D g2 (Graphics2D) g
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASIN
G, RenderingHints.VALUE_ANTIALIAS_ON)
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY)
super.paintComponent(g2) g2.translate(getWidth(
)/2,getHeight()/2) g2.setColor(Color.green)
g2.fillOval(-taille/2,-taille/2, taille,
taille) g2.setColor(Color.black)
g2.setStroke(new BasicStroke(14,
BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL))
g2.drawOval(-taille/2,-taille/2, taille,
taille) double angleH 2Math.PI (minutes -
360) / (1260) double angleM 2Math.PI
(minutes - 15) / 60 GeneralPath gp new
GeneralPath() gp.moveTo((int)(0.3tailleMath.c
os(angleH)), (int)(0.3tailleMath.sin
(angleH))) gp.lineTo(0,0)
gp.lineTo((int)(0.4tailleMath.cos(angleM)),
(int)(0.4tailleMath.sin(angleM)))
g2.draw(gp)
23Courbes de Bézier
- Elles sont quadratiques ou cubique.
- Elles ont trois ou quatre points deux contrôle,
dont deux sont des extrémités. - La courbe est contenue dans le polygône de
contrôle formé des trois ou quatre points.
24Construction
- Un constructeur de courbe cubique, en double
CubicCurve2D.Double(double x1, double y1, double
ctrlx1, double ctrly1,double ctrlx2, double
ctrly2, double x2, double 2)
- Variantes utiles
- les mêmes valent pour les courbes quadratiques.
CubicCurve2D.Double() // initialisée Ã
zéro CubicCurve2D.setCurve(double coords, int
offset) // affecte les valeurs CubicCurve2D.setCur
ve(Point2D pts, int offset) CubicCurve2D.setCur
ve(Point2D p1, Point2D cp1, Point2D cp2, Point2D
p2)
25Aires
- Formes que lon peut composer par des opérations
booléennes (constructive solid geometry en 2D) - Toute forme est un composant
- Les opérations sont
- add
- subtract
- intersect
- exclusiveor
26Aires opérateurs
public void paintComponent(Graphics g)
Graphics2D g2 (Graphics2D)g ... Area
areaOne new Area(ellipse) Area areaTwo new
Area(rectangle) if (option.equals("add"))
areaOne.add(areaTwo) else if
(option.equals("intersection"))
areaOne.intersect(areaTwo) else if
(option.equals("subtract")) areaOne.subtract(areaT
wo) else if (option.equals("exclusive or"))
areaOne.exclusiveOr(areaTwo)
g2.setPaint(Color.orange) g2.fill(areaOne)
g2.setPaint(Color.black) g2.draw(areaOne)
27Découpage
- On peut restreindre la zone à (re)dessiner de
deux manières - par la définition d'une forme de découpe
(clipping) - par la spécification d'un rectangle de
rafraîchissement dans la méthode repaint(). - Un contexte graphique contient un rectangle de
découpe - initialement toute la zone de dessin
- modifiable par setClip() le rectangle ne peut que
diminuer - La méthode repaint() de Component peut prendre en
argument un rectangle, et limiter ainsi l'action
à ce rectangle.
repaint() repaint(long tm) repaint(int x, int y,
int width, int height) repaint(long tm, int x,
int y, int width, int height)
28Un exemple
- Dans le rectangle bleu, on "repeint" des petits
carrés, faisant ainsi apparaître le fond blanc.
class Repeindre extends Frame Repeindre()
setTitle("Repeindre") addMouseListener(new
Reveleur()) setSize(300,300)
setVisible(true) Graphics g
getGraphics() g.setColor(Color.blue)
g.fillRect(0, 0, getSize().width,
getSize().height) g.dispose() class
Reveleur extends MouseAdapter public void
mousePressed(MouseEvent e)
repaint(e.getX(), e.getY(), 30, 30)
public static void main(String args) new
Repeindre()
29Un deuxième exemple
- On choisit une ellipse comme région de découpage.
On dessine une image qui paraît être
partiellement révélée. - Lusage de la propriété opaque donne dautres
effets.
class ImagePanel extends JPanel private
Image image private Ellipse2D oeil new
Ellipse2D.Double() private boolean pressed
false public ImagePanel() image new
ImageIcon("mandrill.jpg").getImage()
setPreferredSize( new Dimension(image.getWid
th(this),image.getHeight(this))) ...
setBackground(Color.black) ...
30Laffichage
- On ne peint que la partie qui est visible Ã
travers loeil - et on modifie lellipse en fonction de position
de la souris
public void paintComponent(Graphics g)
super.paintComponent(g) int width
getSize().width int height
getSize().height if (pressed)
g.setClip(oeil) g.drawImage(image, 0, 0,
this)
public void mouseDragged(MouseEvent e)
oeil.setFrameFromCenter(e.getX(), e.getY(),
e.getX() 100, e.getY() 50) repaint()
31Découverte
- La modification de lopacité empêche le
rafraîchissement de la fenêtre cest comme dans
un jeu où on gratte.
public void mousePressed(MouseEvent e)
pressed true oeil.setFrameFromCenter(e.getX()
, e.getY(), e.getX() 100, e.getY() 50) if
((e.getModifiers() MouseEvent.BUTTON3_MASK)!0)
setOpaque(!isOpaque()) repaint()
32Couleurs
- La classe Color permet de gérer les couleurs.
Constantes - black, blue, cyan, darkGray, gray, green,
lightGray, magenta, orange, pink, red, white,
yellow. - Constructeurs rgb, p.ex. Color(int r, int g, int
b) - Conversion RGBtoHSB (hue, saturation, brightness)
et vice-versa. - La classe dérivée SystemColor contient des noms
symboliques pour les couleurs du système
contrôle, fenêtre active, menu, ombre (inspiré de
Windows). - Le coefficient alpha indique la transparence (0
opaque, 1 transparent)
33Gribouilleur
public class JGribouille public static void
main(String args) JFrame f new
JFrame("Gribouille") f.setContentPane(new
Gribouilleur()) f.pack()
f.setVisible(true) f.setBackground(Color.yell
ow) f.addWindowListener(new Fermeur())
class Gribouilleur extends JPanel int
xd, yd, x, y Gribouilleur()
setPreferredSize(new Dimension(400,250))
addMouseListener(new Appuyeur())
addMouseMotionListener(new Dragueur())
setOpaque(false) public void
paintComponent(Graphics g) Graphics2D g2
(Graphics2D) g g2.setStroke(new
BasicStroke(3)) g2.drawLine(xd, yd, x, y)
xd x yd y ...
... class Appuyeur extends MouseAdapter
public void mousePressed(MouseEvent e) xd
e.getX() yd e.getY() class Dragueur
extends MouseMotionAdapter public void
mouseDragged(MouseEvent e) x e.getX() y
e.getY() repaint()
34ColorChooser
- Un composant de sélection de couleur est fourni.
Il opère en plusieurs modèles par défaut, et peut
être configuré. - Ici, initialisé avec couleur de fond.
- Le bouton qui appelle le sélectionneur est dans
un panneau.
JButton colorButton new JButton("Couleurs...")
colorButton.addActionListener(new
ActionListener() public void
actionPerformed(ActionEvent ae) Color c
JColorChooser.showDialog(Panneau.this,
"Sélection...", getBackground()) if (c !
null) setBackground(c) )
35Exemple
public class Gribouille3 extends Applet int
xd, yd, x, y Color c Color.black Button
nettoyer Choice couleurs public Gribouille3()
setBackground(Color.blue) nettoyer new
Button("effacer") nettoyer.setForeground(Color.
black) nettoyer.setBackground(Color.lightGray)
couleurs new Choice() couleurs.addItem("bl
ack") couleurs.addItem("red")
couleurs.addItem("yellow") couleurs.addItem("gr
een") couleurs.setForeground(Color.black)
couleurs.setBackground(Color.lightGray) public
void init() add(nettoyer) add(new
Label("coloris ")) add(couleurs)
addMouseListener(new Appuyeur())
addMouseMotionListener(new Dragueur())
nettoyer.addActionListener(new Nettoyeur())
couleurs.addItemListener(new Coloreur())
public void update(Graphics g)
g.setColor(c) paint(g) public void
paint(Graphics g) g.drawLine(xd, yd, x, y)
xd x yd y
36Exemple (suite)
- L'Appuyeur relève la position
class Nettoyeur implements ActionListener
public void actionPerformed(ActionEvent e)
Graphics g getGraphics() g.clearRect(0,0,getS
ize().width, getSize().height)
g.dispose()
class Appuyeur extends MouseAdapter public
void mousePressed(MouseEvent e) xd
e.getX() yd e.getY()
- Le Coloreur relève la nouvelle couleur
class Coloreur implements ItemListener public
void itemStateChanged(ItemEvent e) String a
(String) e.getItem() if
(a.equals("black")) c Color.black else
if (a.equals("red")) c Color.red else if
(a.equals("yellow")) c Color.yellow
else if (a.equals("green")) c
Color.green else c Color.pink
- Le Dragueur relève la nouvelle position et
demande le dessin
class Dragueur extends MouseMotionAdapter
public void mouseDragged(MouseEvent e) x
e.getX() y e.getY() repaint()
37Dégradés et textures
- GradientPaint et TexturePaint implémentent Paint
- GradientPaint crée un dégradé entre deux couleurs
données en deux points - TexturePaint répète une image plaquée dans un
rectangle jusquà remplir la forme.
Paint paint new GradientPaint(0, 0, Color.red,
(float)getWidth()/2, (float)getHeight()/2,
Color.blue) g2.setPaint(paint) g2.fill(ellipse)
Rectangle2D anchor new Rectangle2D.Double(0,
0, 4 bufferedImage.getWidth(), 4
bufferedImage.getHeight()) Paint paint new
TexturePaint(bufferedImage, anchor)
38La composition
- Il y a 8 modes de composition de limage
construite avec limage existante, numérotées par
des constantes de la classe AlphaComposite. - Le coefficient alpha ne change pas ces modes,
mais atténue seulement limpact de limage
construite. - s alpha de source, d alpha de destination, le
coefficient final du mélange est s(1-d) ou
d(1-s). - On choisit le style de composition par
- Encore faut-il que lécran accepte une couche
alpha. En général cest non, et on dessine dans
une image que lon affiche.
Composite composite AlphaComposite.getInstance(r
ule, alpha) g2.setComposite(composite)
39Illustration (1)
- Le programme dessine une ellipse rouge en alpha
1 et, selon le choix de la règle de composition,
la compose avec un rectangle bleu. - De dessin se fait dans une BufferedImage, pour
profiter de la couche alpha.
public void paintComponent(Graphics g)
super.paintComponent(g) Graphics2D g2
(Graphics2D)g if (image null) image
new BufferedImage(getWidth(),getHeight(),
BufferedImage.TYPE_INT_ARGB) Graphics2D gI
image.createGraphics() gI.setPaint(Color.red)
gI.fill(ellipse) AlphaComposite composite
AlphaComposite.getInstance(rule, alpha)
gI.setComposite(composite) gI.setPaint(Color.bl
ue) gI.fill(rectangle) g2.drawImage(image,
null, 0, 0)
40Illustration (2)
- Le choix de la règle se fait par lecture de la
comboBox - le calcul de alpha se fait par lecture dans le
curseur (et division par 100)
if (r.equals("CLEAR)) rule AlphaComposite.CLEA
R else if (r.equals("SRC")) rule
AlphaComposite.SRC else if (r.equals("SRC_OVER"))
rule AlphaComposite.SRC_OVER else if
(r.equals("DST_OVER")) rule
AlphaComposite.DST_OVER etc.
a curseur.getValue() alpha (float)a / 100.0F
41Transformations affines
- Les transformations affines servent à modifier
les coordonnées utilisateur avant affichage - Par exemple, le repère peut être centré au milieu
de la zone de dessin. - Les transformations sont
- rotation
- translation
- dilatation
- cisaillement (shear)
- La class AffineTransform permet de créer et de
composer des transformations affines. De
nombreuses méthodes existent.
42Opérations
- Mathématiquement, une transformation affine est
représentée par une matrice 3 x 3 dont la
dernière ligne est toujours (0 0 1). - Seuls les 6 autres coefficients sont conservés.
On peut donner ces coefficients explicitement, ou
les faire calculer en fonction de la nature de
lopération recherchée. - Créations
- Compositions
AffineTransform t new AffineTransform() t.setTo
Rotation(angle) t.setToTranslation(dx,
dy) t.setToScale(sx, sy) t.setToShear(cx,cy)
t.rotate(angle) t.translate(dx, dy) t.scale(sx,
sy) t.shear(cx,cy)
43Utilisation exemple
- Quand la transformation est définie, on lutilise
en lajoutant à la transformation courante par
public void paintComponent(Graphics g)
super.paintComponent(g) Graphics2D g2
(Graphics2D)g g2.translate(getWidth() / 2,
getHeight() / 2) g2.setPaint(Color.gray)
g2.draw(square) g2.transform(t)
g2.setPaint(Color.red) g2.fill(smallsquare)
g2.setPaint(Color.black) g2.draw(square)
44Exemple
- Ici, composer est une variable booléenne qui
conserve létat de la coche.
public void actionPerformed(ActionEvent event)
JToggleButton source (JToggleButton)
event.getSource() // le bouton String
sourceAction source.getActionCommand() // son
libellé if (sourceAction.equals("composer"))
// la coche composer source.isSelected()
return if (!composer) t.setToIdentity()
// composer ou non ? if (sourceAction.equals("r
otation")) t.rotate(Math.toRadians(30))
else if (sourceAction.equals("translater"))
t.translate(20, 15) else if (sourceAction.equal
s("dilater")) t.scale(2.0, 1.5) else if
(sourceAction.equals("cisailler"))
t.shear(-0.2, 0) repaint()
45Transformation affine implicite
- Laffichage, lors de lexécution dun
paintComponent, est optimisé. Seule la zone qui
doit être rafraîchie lest vraiment, et cela
dépend bien sûr de lévénement qui a provoqué
laffichage. - Le context graphique maintient une transformation
affine qui contient la translation du composant
daffichage par rapport au rectangle de
réaffichage. Cette transformation implicite ne
doit pas être ignorée, mais utilisée. - On ajoutera donc des transformations, au lieu de
les remplacer. - Moyennant cette précaution, le décalage est
transparent à lutilisateur.
46Exemple
- Toute opération graphique se fait relativement au
panneau jaune. - Lorigine est le coin supérieur gauche du
panneau. - Les valeurs numériques donnent la position de la
souris relativement à lorigine (elle est Ã
lorigine de la zone bleue).
- La transformation affine affichée indique la
translation de lorigine du panneau jaune par
rapport à lorigine de la zone qui a été
redessinée. Dans le cas présent, cette origine
est la zone de texte.
47Exemple (suite)
- Ici, lorigine est la zone grise, après un
déplacement de la barre verticale du panneau
mouvant. - Une déiconification, ou le lancement, donnent
lorigine dans la zone bleue, un déplacement du
panneau horizontal dans la zone blanche.
- Les informations sobtiennent par
public void paintComponent(Graphics g)
Graphics2D g2 (Graphics2D) g
... AffineTransform at g2.getTransform() txt.
setText(at.toString()) ... g2.draw(new
Ellipse2D.Float(w/4,h/4, w/2, h/2))
48Rendu
- Le rendu est amélioré (au dépens de la rapidité)
par un ensemble de hints (conseils). - Chaque conseil concerne un aspect et indique un
souhait. - Un conseil se présentent donc comme un couple
clé dune propriété et valeur de cette propriété. - On peut aussi écrire
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASIN
G, RenderingHints.VALUE_ANTIALIAS_ON) g2.setR
enderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY)
RenderingHints r ... g2.setRenderingHints(r)
49Rendu suite
- Les aspects du rendu concernent lanti-aliasing,
la couleur, linterpolation
KEY_ANTIALIASING VALUE_ANTIALIAS_DEFAULT
VALUE_ANTIALIAS_OFF VALUE_ANTIALIAS_ON
KEY_RENDERING VALUE_RENDER_DEFAULT
VALUE_RENDER_QUALITY VALUE_RENDER_SPEED
KEY_ALPHA_INTERPOLATION KEY_COLOR_RENDERING
KEY_DITHERING KEY_INTERPOLATION
VALUE_ALPHA_INTERPOLATION_DEFAULT
VALUE_ALPHA_INTERPOLATION_QUALITY
VALUE_ALPHA_INTERPOLATION_SPEED
KEY_FRACTIONALMETRICS KEY_TEXT_ANTIALIASING