Le placement des composants (1/2) Tout composant a un placement dans son origine conteneur, donné par son origine et ses dimensions Le rectangle est géré par getBounds() et hauteur largeur setBounds(Rectangle) La position (origine) est gérée par getLocation() et setLocation(Point) La taille est gérée par getSize() et setSize(Dimension) Interfaces graphiques en Java 1 Le placement des composants (2/2) Les tailles "idéale", maximale et minimale sont retournées par getPreferredSize() getMaximalSize() getMinimalSize() Les marges sont entre les bords et les composants Les marges d’un conteneur sont représentées par une instance de la classe Insets : • quatre champs pour les 4 marges • constructeur Insets(top, left, bottom, right) Les marges comprennent le bord, et pour Frame, aussi la barre de titre ! Pour changer de marges, on redéfinit la méthode getInsets()de la classe Container Les gestionnaires de géométrie (LayoutManager) utilisent ces informations pour placer les composants dans un conteneur. Interfaces graphiques en Java 2 Gestion des LayoutManager Pour spécifier/consulter/modifier les LayoutManager, on utilise les modifieurs et accesseurs setLayout et getLayout Le recalcul des positions après modification du LayoutManager ne prend effet qu’après : modification de la taille du conteneur demande de recalcul par validate() (méthode de Component dans AWT) ou revalidate() (méthode de JComponent dans Swing) forçage du recalcul par layoutContainer(cont) (méthode de classe de LayoutManager) ou doLayout() (méthode de Container qui appelle layoutContainer(this)) Pour les Window et Frame, la méthode pack() entraine le redimensionnement du conteneur qui prend la taille minimale pour contenir ses composants, en fonction de la taille préférée des composants. Interfaces graphiques en Java 3 Composants valides et invalides Un composant est valide s’il est correctement positionné et dimensionné ainsi que tous ses sous-composants (méthode isValid()) validate() réorganise un composant invalidé par appel à doLaoyout(), et le marque comme valide ne fait rien sur un composant valide (même si un descendant est invalidé) invalidate() marque comme invalidé le composant et tous ses ascendants revalidate() provoque la remontée de l’arbre d’instances à la recherche du premier conteneur pour lequel isValidateRoot() est vrai. Le sous-arbre de ce conteneur est réaffiché (après distribution des évènements en attente). Interfaces graphiques en Java 4 Les gestionnaires de géométrie d’AWT Gère la disposition des composants dans un conteneur Les gestionnaires par défaut sont Object BorderLayout BorderLayout pour CardLayout • Window • Frame • Dialog LayoutManager2 GridBagLayout GridLayout FlowLayout pour LayoutManager • Panel • Applet FlowLayout GridBagConstraints LayoutManager et LayoutManager2 sont des interfaces Interfaces graphiques en Java 5 FlowLayout FlowLayout : les composants sont gérés comme les mots d’un texte, ils sont alignés de la gauche vers la droite et on passe à la ligne quand il n’y a plus de place une quatre FlowTest Frame f = new Frame("FlowTest"); f.setLayout(new FlowLayout()); f.add(new Button("A")); f.add(new Button("B")); f.add(new Button("C")); f.add(new Button("D")); f.add(new Button("E")); Interfaces graphiques en Java trois deux cinq FlowRightTest Frame f = new Frame("FlowRightTest"); f.setLayout(new FlowLayout(FlowLayout.RIGHT,20,20)); f.add(new Button("A")); f.add(new Button("B")); f.add(new Button("C")); f.add(new Button("D")); f.add(new Button("E")); 6 BorderLayout BorderLayout : les composants sont positionnés et dimensionnés dans 5 zones : "nord" et "sud" occupent toute la largeur "ouest" et "est" occupent la hauteur qui reste "centre" occupe la place restante North West Center East Frame f = new Frame("orderTest"); f.setLayout(new BorderLayout()); f.add(new Button("Nord"),BorderLayout.NORTH); f.add(new Button("Sud"),BorderLayout.SOUTH); f.add(new Button("Est"),BorderLayout.EAST); f.add(new Button("Ouest"),BorderLayout.WEST); f.add(new Button("Centre"),BorderLayout.CENTER); South BorderTest1 Interfaces graphiques en Java 7 BorderLayout et FlowLayout Panel flow = new Panel(new FlowLayout()); flow.add(new Button("A")); flow.add(new Button("B")); flow.add(new Button("C")); flow.add(new Button("D")); flow.add(new Button("E")); Panel border = new Panel(new BorderLayout()); border.add(flow, BorderLayout.NORTH); border.add(new Button("Sud"),BorderLayout.SOUTH); border.add(new Button("Est"),BorderLayout.EAST); border.add(new Button("Ouest"),BorderLayout.WEST); border.add(new Button("Centre"),BorderLayout.CENTER); Frame f = new Frame("BorderTest2"); f.add(border); BorderTest2 Interfaces graphiques en Java 8 GridLayout GridLayout : chaque cellule a même taille, on fixe le nombre de lignes et de colonnes de la grille, ainsi que les espacements entre composants un deux trois quatre cinq six GridLayoutTest Panel c = new Panel(); c.setLayout(new GridLayout(2,0,3,3)); c.setBackground(Color.blue); c.add(new Button("1")); List l = new List(); l.add("un"); l.add("deux"); l.add("trois"); c.add(l); c.add(new Button("2")); c.add(new Button("3")); c.add(new Button("5")); c.add(new Button("6")); c.add(new Button("extra-large")); this.add(c); this.pack(); this.setVisible(true); Interfaces graphiques en Java 9 GridBagLayout (1/2) GridbagLayout : les composants sont placés dans une grille, chaque composant porte des contraintes de taille et de placement exprimées dans un objet GridBagConstraints attribut de l’objet GridBagConstraints Valeur par défaut anchor CENTER fill Valeurs possibles spécifie CENTER, EAST, NORTH, NORTHEAST,... WEST où ancrer le composant dans sa zone NONE BOTH, HORIZONTAL, VERTICAL, NONE remplissage de sa zone par le composant gridx,gridy RELATIVE RELATIVE, ou entiers position en absolu, ou à gauche, resp. en dessous gridwidth, gridheight 1, 1 RELATIVE, REMAINDER, ou entiers largeur et hauteur de la zone, en absolu, à gauche, en dessous, ou ce qui reste sur la ligne (colonne) weightx,weighty 0,0 doubles poids donné à la colonne (ligne), l'élargit en conséquence Interfaces graphiques en Java 10 GridBagLayout (2/2) JButton button; this.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.weightx = 1.0; button = new JButton("Bouton 1");this.add(button, button = new JButton("Bouton 2");this.add(button, button = new JButton("Bouton 3");this.add(button, c.gridwidth = GridBagConstraints.REMAINDER; button = new JButton("Bouton 4");this.add(button, c); c); c); c); button = new JButton("Bouton 5");this.add(button,c); c.gridwidth = GridBagConstraints.RELATIVE; button = new JButton("Bouton 6");this.add(button, c); c.gridwidth = GridBagConstraints.REMAINDER; button = new JButton("Bouton 7");this.add(button, c); c.gridwidth = 1; c.gridheight = 2;c.weighty = 1.0; button = new JButton("Bouton 8");this.add(button,c); c.gridwidth = GridBagConstraints.REMAINDER; c.gridheight = 1; button = new JButton("Bouton 9");this.add(button,c); c.weighty = 0.0; button = new JButton("Bouton 10");this.add(button,c); GridBagLayoutTest Interfaces graphiques en Java 11 CardLayout CardLayout : permet d’afficher les composants comme un tas de cartes, seul le composant du dessus est visible Des méthodes de parcours de la pile (first(), next(), previous(), last()) et une méthode de saut (show(String)). JTabbedPane dans Swing est plus pratique super("CardLayoutTest"); cards = new Panel(); cards.setLayout(new CardLayout()); Panel p1 = new Panel(); Panel p2 = new Panel(); Button ok = new Button("OK"); Button quit = new Button("Quit"); Button next1 = new Button("Next"); next1.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ next("second"); } }); p1.add(ok); p1.add(quit); CardLayoutTest p1.add(next1); Interfaces graphiques en Java TextField tfield = new TextField("Login:", 20); Button next2 = new Button("Next"); next2.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ next("first"); } }); p2.add(tfield); p2.add(next2); cards.add("first",p1); cards.add("second",p2); this.add(cards); this.pack(); this.setVisible(true); 12 LayoutManager de Swing Swing propose d’autres LayoutManager : liés à des composants, par exemple ScrollPaneLayout pour les JScrollPanel généraux pour utilisation dans des conteneurs, BoxLayout et SpringLayout Les LayoutManager par défaut sont : FlowLayout pour JPanel le contentPane d’une JFrame a par défaut un BorderLayout Interfaces graphiques en Java 13 BoxLayout Arrange ses composants en une ligne ou une colonne, en respectant leurs tailles préférées : on obtient en combinant des BoxLayout le même effet qu’avec GridBagLayout mais en plus simple Le composant Box est un conteneur dont le gestionnaire est BoxLayout et qui est fils de Container (pas dans Swing). Box permet d’ajouter des struts, blocs de taille fixe, de la glue qui fait du remplissage et des aires rigides BoxLayoutTest Interfaces graphiques en Java Box b1 = new Box(BoxLayout.Y_AXIS); Button button = new Button("Button 1"); b1.add(button); button = new Button("Button 2"); button.setPreferredSize(new Dimension(200,100)); b1.add(button); Box b2 = new Box(BoxLayout.X_AXIS); button = new Button("Button 3"); b2.add(button); button = new Button("Button 4"); button.setPreferredSize(new Dimension(200, 100)); b2.add(button); b1.add(b2); this.add(b1); 14 SpringLayout Le SpringLayout se base sur les relations entre les bords des composants et sur des contraintes portées par les positions et dimensions des composants (contrainte « ressort » spécifiant les valeurs minimum et maximum entre lesquelles la variable peut varier, et une valeur préférée) Container contentPane = this.getContentPane(); SpringLayout layout = new SpringLayout(); contentPane.setLayout(layout); JLabel label = new JLabel("Label: "); JTextField textField = new JTextField("Text field", 15); contentPane.add(label); contentPane.add(textField); SpringLayout.Constraints labelCons = layout.getConstraints(label); labelCons.setY(Spring.constant(5)); SpringLayout.Constraints textFieldCons = layout.getConstraints(textField); textFieldCons.setY(Spring.constant(5)); textFieldCons.setWidth(Spring.constant(50)); layout.putConstraint(SpringLayout.WEST, label, 20, SpringLayout.WEST, contentPane); layout.putConstraint(SpringLayout.WEST, textField, 5, SpringLayout.EAST, label); SpringLayoutTest Interfaces graphiques en Java 15 Le dessin en Java Object En Java 1.1, les outils de dessin sont assez rudimentaires . Graphics des méthodes draw*() et fill*() pour lignes, Point choix de deux modes de dessin : direct ou xor une zone de découpe (clipping) rectangulaire. Polygon Rectangle Font FontMetrics Image Color Interfaces graphiques en Java rectangles, ovales, polygones Java 2 propose des techniques plus sophistiquées. le “double buffering” est automatique par défaut dans les classes Swing. une hiérarchie de classes Shape pour dessiner différentes formes Java2D pour le dessin 2D, Java3D pour la 3D 16 Les dessins en AWT (1/2) Graphics fournit à la fois le canal d'affichage et les outils de dessin. Image pour les images (il existe aussi une API JavaAdvancedImaging (JAI) non incluse dans le SDK) Shape est une interface pour les formes géométriques telles que Polygon, Rectangle, ... Font, FontMetrics pour les polices Color pour la couleur Java2D est une extension de AWT proposant de nombreuses classes avec beaucoup de possibilités de dessin et de manipulation d’images Java 2D utilise la classe Graphics2D qui dérive de Graphics. Interfaces graphiques en Java 17 Contexte graphique L'outil de dessin est le contexte graphique, objet de la classe Graphics (ou Graphics2D). Il encapsule l'information nécessaire, sous forme d'état graphique. Chaque composant peut accéder implicitement et explicitement à un contexte graphique. Un contexte graphique 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) Un contexte graphique offre des méthodes de dessin Interfaces graphiques en Java 18 Exemple sur Graphics2D ... public void paint(Graphics g){ Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Dimension d = this.getSize(); ... g2.setColor(Color.lightGray); g2.setStroke(new BasicStroke(2.0f)); g2.draw(new Line2D.Double(x, y+rectHeight-1, x + rectWidth, y)); g2.drawString("Line2D", x, stringY); ... g2.setStroke(stroke); g2.draw(new Rectangle2D.Double(x, y, rectWidth, rectHeight)); g2.drawString("Rectangle2D", x, stringY); ... } ... Graphics2DTest Interfaces graphiques en Java 19 Look and Feel En Swing, l’apparence des composants est gérée indépendamment du système d’exploitation via un LookAndFeel Au moins 3 “look and feel” sont fournis avec le SDK de Sun com.sun.java.swing.plaf.windows.WindowsLookAndFeel com.sun.java.swing.plaf.motif.MotifLookAndFeel javax.swing.plaf.metal.MetalLookAndFeel On peut bien sur créer son propre look and feel UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); SwingUtilities.updateComponentTreeUI(this); LookAndFeelTest Interfaces graphiques en Java 20