Boîtes à outils graphiques Faire une interface graphique avec Java2d et Swing Boîte à outils graphique = ensemble de classes Java permettant de développer des interfaces hommemachine Il faut : Pouvoir définir une apparence graphique Écouter les actions de l utilisateur Dans ce cours AWT vs. Swing Nous utilisons les boîtes à outils AWT (Abstract Window Toolkit) et Swing. La plupart des classes de Swing ont leur équivalent en AWT => Alors pourquoi AWT+Swing et non pas simplement AWT? Chaque plateforme (Windows, Unix, Mac ) dispose de ses propres éléments graphiques (fenêtres, boutons, etc.) Windows 2000 Mac OS X
AWT vs. Swing Avec Swing, on peut définir le "look and feel" de son interface. => Le rendu sera le même quelle que soit la plateforme Définir le rendu graphique d une interface Windows 2000 Mac OS X Hiérarchie de composants graphiques Top-level conteneurs Les éléments d une interface sont organisés selon une hiérarchie. La racine est un composant conteneur "toplevel" Les nœuds sont des composants conteneurs Les feuilles sont de simples composants ou des composants conteneurs JFrame (application) JDialog (dépendant d'un autre top-level) JApplet (applet)
Nœuds conteneurs intermédiaires Les feuilles On utilise des composants de la classe : - javax.swing.jpanel - javax.swing.jscrollpane - Dans un premier temps, nous nous intéressons aux composants prédéfinis de swing (Swing widgets) Nous verrons plus tard comment faire nos propres composants Les Swing widgets Plus d exemples Voir : http://java.sun.com/docs/books/tutorial/uiswing/components/components.html JButton Quelques exemples : javax.swing.jbutton javax.swing.jcomponent JLabel (avec ou sans image) javax.swing.jcheckbox JTextField (+JPasswordField + JFormatedTextField)
Plus d exemples Exemple d une hiérarchie Javax.swing.JFrame Conteneur de top-level JSlider JComboBox JSpinner Javax.swing.JPanel Javax.swing.JButton Javax.swing.JComponent Javax.swing.JCheckbox JList JProgressBar Exemple d une hiérarchie Et la mise en page? JFrame frame = new JFrame("Example JFrame"); Container container1 = frame.getcontentpane(); JPanel bluepanel = new JPanel(); bluepanel.setbackground(new Color(0, 0, 200)); JTextField component1 = new JTextField("component1"); JCheckBox component2 = new JCheckBox("component2"); JButton component3 = new JButton("component3"); GridLayout layoutbluepanel = new GridLayout(2, 1); layoutbluepanel.setvgap(3); bluepanel.setlayout(layoutbluepanel); container1.add(bluepanel); container1.add(component3); bluepanel.add(component1); bluepanel.add(component2); frame.pack(); Comment obtenir cette organisation spatiale? => Il faut spécifier la mise en page des différents nœuds et feuilles.
La mise en page : les layouts managers Un layout manager est un objet qui, associé à un conteneur C, détermine la taille et la position des composants graphiques qui appartiennent à C. Conteneur de top-level LayoutManager Les layout managers : layout absolu JFrame frame = new JFrame("Example JFrame"); frame.setsize(280, 130); Container container1 = frame.getcontentpane(); container1.setlayout(null); JTextField component1 = new JTextField("component1"); component1.setbounds( 25, 10, (int)component1.getpreferredsize().getwidth(), (int)component1.getpreferredsize().getheight()); JCheckBox component2 = new JCheckBox("component2"); component2.setbounds( 100, 60, (int)component2.getpreferredsize().getwidth(), (int)component2.getpreferredsize().getheight()); frame.getcontentpane().add(component1); frame.getcontentpane().add(component2); Les layout managers : BorderLayout C est le layout manager par défaut pour les conteneurs de top-level. Cinq Fils Nord Est Sud Ouest Centre Nord prend toute la largeur disponible (getwidth()) mais juste sa hauteur préférée (getpreferredsize()) ainsi de suite et Center prend tout ce qui reste container.add(mycomponent, BorderLayout.NORTH); Reprenons notre exemple JFrame frame = new JFrame("Example JFrame"); Container container1 = frame.getcontentpane(); JPanel bluepanel = new JPanel(); bluepanel.setbackground(new Color(0, 0, 200)); JTextField component1 = new JTextField("component1"); JCheckBox component2 = new JCheckBox("component2"); JButton component3 = new JButton("component3"); GridLayout layoutbluepanel = new GridLayout(2, 1); layoutbluepanel.setvgap(3); bluepanel.setlayout(layoutbluepanel); container1.add(bluepanel, BorderLayout.CENTER); container1.add(component3, BorderLayout.EAST); bluepanel.add(component1); bluepanel.add(component2); frame.pack();
pack qu est-ce que c est? Spécifier la dimension préferrée (ex : JScrollPane) frame.pack(); Chaque composant a une dimension préferrée (getpreferredsize()) La méthode pack exécute la mise en page en fonction des layouts managers des conteneurs et des dimensions préferrées des composants feuilles. JTextArea textarea = new JTextArea(); textarea.setpreferredsize(new Dimension(400, 1000)); JScrollPane scrollpane = new JScrollPane(textArea); scrollpane.setpreferredsize(new Dimension(400, 400)); JFrame frame = new JFrame("Scrollable JPanel"); frame.getcontentpane().add(scrollpane, BorderLayout.CENTER); frame.pack(); Attention : En général, on ne change pas La dimension préferrée des Swing widgets La crème du layout manager : Le GridBagLayout Application graphique : 2 processus C est le plus flexible (on peut spécifier les espaces, comment se passe le redimensionnement, etc.) mais aussi le plus compliqué Exemple au tableau : Dès qu une fenêtre est rendue visible, le programme ne termine pas à la fin du main. Pour que le programme se termine quand on ferme la fenêtre : frame.setdefaultcloseoperation( Jframe.EXIT_ON_CLOSE);
Définir le rendu graphique d un composant Définir le rendu graphique d un composant Le rendu graphique des composants est assuré par le thread awt (cf. cours suivant). Pour assurer la fluidité, Swing utilise un mécanisme de double-buffering. Le thread awt se charge d appeler repaint() sur les composants quand cela est nécessaire : le composant devient visible, il est redimensionné repaint() appelle paint() dès que c est possible. On ne force pas un appel à paint(), on appelle repaint(). Pour les composants standard, le rendu déjà défini par Swing, on le redéfinit pas en général. Pour définir le rendu graphique d un composant, on fait généralement une sous-classe de JComponent ou Jpanel dans laquelle on redéfinit la méthode paint. La méthode paint(graphics g) permet de récupérer un contexte graphique dans lequel dessiner Il faut caster en Graphics2D pour disposer de toutes les fonctionnalités de la librairie Java2D public class MyComponent extends JPanel { public void paint(graphics g) { Graphics2D g2d = (Graphics2D)g; Dessiner des primitives graphiques Java2D Le contexte du graphics2d public class MyComponent extends JPanel { Image logo; public MyComponent() { Toolkit tk = Toolkit.getDefaultToolkit(); logo = tk.getimage("ups11-logo.jpg"); try { MediaTracker tracker = new MediaTracker(this); tracker.addimage(logo, 0); tracker.waitforid(0); catch(exception e) { e.printstacktrace(); public void paint(graphics g) { Graphics2D g2d = (Graphics2D)g; g2d.filloval(150, 250, 200, 100); g2d.drawrect(200, 40, 100, 200); g2d.drawstring("hello", 30, 300); g2d.drawimage(logo, 0, 0, this); (0, 0) Le contexte graphique est défini par : des attributs de style : - java.awt.paint (ex: java.awt.color ) - java.awt.stroke (ex: java.awt.basicstroke ) - java.awt.font des attributs géométriques : - java.awt.geom.affinetransform des attributs définissant la qualité : - java.awt.renderinghints
Le contexte du graphics2d Des primitives plus évoluées public void paint(graphics g) { Graphics2D g2d = (Graphics2D)g; g2d.setcolor(color.red); g2d.filloval(150, 250, 200, 100); g2d.setstroke(new BasicStroke(4)); g2d.drawrect(200, 40, 100, 200); g2d.setcolor(color.black); g2d.setfont(new Font("verdana", Font.ITALIC, 24)); g2d.drawstring("hello", 30, 300); AffineTransform transf = new AffineTransform(); transf.translate(10, 20); transf.rotate(math.pi/4); g2d.settransform(transf); g2d.drawimage(logo, 0, 0, this); interface java.awt.shape Ex : Ellipse, Rectangle, Segments, Polylignes GeneralPath gp = new GeneralPath(); gp.moveto(60, 30); gp.lineto(90, 60); gp.lineto(30, 60); gp.closepath(); g2d.fill(gp);