t
t
t
t
t t 13) Création de fenêtres & d'Applets
tttt
13) Création de fenêtres & d'Applets
Texte original t Traducteur : P. BOITE
t
t
///
Ce chapitre contient 14 pages
1 2 3 4 5 6 7 8 9 10 11 12 13 14
\\\
t t t
t t t
t
t t t
Note that there are many variations you can apply to JFileChooser, including filters to narrow the file names that you will allow. t Remarquons qu'il y a de nombreuses variantes applicables à JFileChooser, parmi lesquelles des filtres pour restreindre les noms de fichiers acceptés.
t t t
For an “open file” dialog, you call showOpenDialog( ), and for a “save file” dialog you call showSaveDialog( ). These commands don’t return until the dialog is closed. The JFileChooser object still exists, so you can read data from it. The methods getSelectedFile( ) and getCurrentDirectory( ) are two ways you can interrogate the results of the operation. If these return null it means the user canceled out of the dialog. t Pour un dialogue d'ouverture de fichier, on appelle showOpenDialog(), et pour un dialogue de sauvegarde de fichier, on appelle showSaveDialog(). Ces commandes ne reviennent que lorsque le dialogue est fermé. L'objet JFileChooser existe encore, de sorte qu'on peut en lire les données. Les méthodes getSelectedFile() et getCurrentDirectory() sont deux façons d'obtenir les résultats de l'opération. Si celles-ci renvoient null, cela signifie que l'utilisateur a abandonné le dialogue.
t t t

HTML on Swing components

t

HTML sur des composants Swing

t t t
Any component that can take text can also take HTML text, which it will reformat according to HTML rules. This means you can very easily add fancy text to a Swing component. For example, t Tout composant acceptant du texte peut également accepter du texte HTML, qu'il reformatera selon les règles HTML. Ceci signifie qu'on peut très facilement ajouter du texte de fantaisie à un composant Swing. Par exemple :
t t t
//: c13:HTMLButton.java
// Putting HTML text on Swing components.
// <applet code=HTMLButton width=200 height=500>
// </applet>
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import com.bruceeckel.swing.*;

public class HTMLButton extends JApplet {
  JButton b = new JButton("<html><b><font size=+2>" +
    "<center>Hello!<br><i>Press me now!");
  public void init() {
    b.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e){
        getContentPane().add(new JLabel("<html>"+
          "<i><font size=+4>Kapow!"));
        // Force a re-layout to
        // include the new label:
        validate();
      }
    });
    Container cp = getContentPane();
    cp.setLayout(new FlowLayout());
    cp.add(b);
  }
  public static void main(String[] args) {
    Console.run(new HTMLButton(), 200, 500);
  }
} ///:~
t
//: c13:HTMLButton.java
// Mettre du texte HTML sur des composants Swing.
// <applet code=HTMLButton width=200 height=500>
// </applet>
importjavax.swing.*;
importjava.awt.event.*;
importjava.awt.*;
importcom.bruceeckel.swing.*;

publicclassHTMLButton extendsJApplet {
JButton b = newJButton("<html><b><font size=+2>"+
   "<center>Hello!<br><i>Press me now!");
publicvoidinit() {
   b.addActionListener(newActionListener() {
     publicvoidactionPerformed(ActionEvent e){
       getContentPane().add(newJLabel("<html>"+
         "<i><font size=+4>Kapow!"));
       // Force un réalignement pour
       // inclure le nouveau label:
       validate();
     }
   });
   Container cp = getContentPane();
   cp.setLayout(newFlowLayout());
   cp.add(b);
}
publicstaticvoidmain(String[] args) {
   Console.run(newHTMLButton(), 200, 500);
}
} ///:~
t t t
You must start the text with “<html>,” and then you can use normal HTML tags. Note that you are not forced to include the normal closing tags. t Le texte doit commencer avec , et ensuite on peut utiliser les tags HTML normaux. Remarquons que les tags de fermeture ne sont pas obligatoires.
t t t
The ActionListener adds a new JLabel to the form, which also contains HTML text. However, this label is not added during init( ) so you must call the container’s validate( ) method in order to force a re-layout of the components (and thus the display of the new label). t L'ActionListener ajoute au formulaire un nouveau JLabel contenant du texte HTML. Comme ce label n'est pas ajouté dans la méthode init(), on doit appeler la méthode validate() du conteneur de façon à forcer une redisposition des composants (et de ce fait un affichage du nouveau label).
t t t
You can also use HTML text for JTabbedPane, JMenuItem, JToolTip, JRadioButton and JCheckBox. t On peut également ajouter du texte HTML à un JTabbedPane, JMenuItem, JToolTip, JRadioButton ou un JCheckBox.
t t t

Sliders and progress bars

t

Curseurs [sliders] et barres de progression [progress bars]

t t t
A slider (which has already been used in the sine wave example) allows the user to input data by moving a point back and forth, which is intuitive in some situations (volume controls, for example). A progress bar displays data in a relative fashion from “full” to “empty” so the user gets a perspective. My favorite example for these is to simply hook the slider to the progress bar so when you move the slider the progress bar changes accordingly: t Un slider(qu'on a déjà utilisé dans l'exemple du sinus) permet à l'utilisateur de rentrer une donnée en déplaçant un point en avant ou en arrière, ce qui est intuitif dans certains cas (un contrôle de volume, par exemple). Un progress bar représente une donnée en remplissant proportionnellement un espace vide pour que l'utilisateur ait une idée de la valeur. Mon exemple favori pour ces composants consiste à simplement lier le curseur à la barre de progression, de sorte que lorsqu'on déplace le curseur la barre de progression change en conséquence :
t t t
//: c13:Progress.java
// Using progress bars and sliders.
// <applet code=Progress
//  width=300 height=200></applet>
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.border.*;
import com.bruceeckel.swing.*;

public class Progress extends JApplet {
  JProgressBar pb = new JProgressBar();
  JSlider sb =
    new JSlider(JSlider.HORIZONTAL, 0, 100, 60);
  public void init() {
    Container cp = getContentPane();
    cp.setLayout(new GridLayout(2,1));
    cp.add(pb);
    sb.setValue(0);
    sb.setPaintTicks(true);
    sb.setMajorTickSpacing(20);
    sb.setMinorTickSpacing(5);
    sb.setBorder(new TitledBorder("Slide Me"));
    pb.setModel(sb.getModel()); // Share model
    cp.add(sb);
  }
  public static void main(String[] args) {
    Console.run(new Progress(), 300, 200);
  }
} ///:~
t
//: c13:Progress.java
// Utilisation de progress bars et de sliders.
// <applet code=Progress
//  width=300 height=200></applet>
importjavax.swing.*;
importjava.awt.*;
importjava.awt.event.*;
importjavax.swing.event.*;
importjavax.swing.border.*;
importcom.bruceeckel.swing.*;

publicclassProgress extendsJApplet {
JProgressBar pb = newJProgressBar();
JSlider sb =
   newJSlider(JSlider.HORIZONTAL, 0, 100, 60);
publicvoidinit() {
   Container cp = getContentPane();
   cp.setLayout(newGridLayout(2,1));
   cp.add(pb);
   sb.setValue(0);
   sb.setPaintTicks(true);
   sb.setMajorTickSpacing(20);
   sb.setMinorTickSpacing(5);
   sb.setBorder(newTitledBorder("Slide Me"));
   pb.setModel(sb.getModel()); // Partage du modèle
   cp.add(sb);
}
publicstaticvoidmain(String[] args) {
   Console.run(newProgress(), 300, 200);
}
} ///:~
t t t
The key to hooking the two components together is in sharing their model, in the line: t La clé du lien entre les deux composant se trouve dans le partage de leur modèle, dans la ligne :
t t t
pb.setModel(sb.getModel());

t
pb.setModel(sb.getModel());
t t t
Of course, you could also control the two using a listener, but this is more straightforward for simple situations. t Naturellement, on pourrait aussi contrôler les deux composants en utilisant un listener, mais ceci est plus direct pour les cas simples.
t t t
The
JProgressBar is fairly straightforward, but the
JSlider has a lot of options, such as the
orientation and major and minor tick marks. Notice how straightforward it is to
add a titled border.
t Le JProgressBar est assez simple, mais le JSlidera un grand nombre d'options, telles que l'orientation et les graduations mineures et majeures. Remarquons la simplicité de l'ajout d'une bordure avec titre.
t t t


Trees


t

Arbres [Trees]

t t t
Using a JTree
can be as simple as saying:

t L'utilisation d'un JTreepeut être aussi simple que ceci :
t t t
add(new JTree(
new Object[] {"this", "that", "other"}));
t
add(newJTree(
newObject[] {"this", "that", "other"}));
t t t
This displays a primitive tree. The API for trees is vast, however—certainly one of the largest in Swing. It appears that you can do just about anything with trees, but more sophisticated tasks might require quite a bit of research and experimentation. t Ceci affiche un arbre rudimentaire. L'API pour les arbres est vaste, probablement une des plus importantes de Swing. On peut faire à peu près tout ce qu'on veut avec des arbres, mais les tâches plus complexes demandent davantage de recherches et d'expérimentations.
t t t
Fortunately, there is a middle ground provided in the library: the “default” tree components, which generally do what you need. So most of the time you can use these components, and only in special cases will you need to delve in and understand trees more deeply. t Heureusement, il y a un niveau intermédiaire fourni dans la bibliothèque : les composants arbres par défaut, qui font en général ce dont on a besoin, de sorte que la plupart du temps on peut se contenter de ces composants, et ce n'est que dans des cas particuliers qu'on aura besoin d'approfondir et de comprendre plus en détail les arbres.
t t t
The following example uses the “default” tree components to display a tree in an applet. When you press the button, a new subtree is added under the currently selected node (if no node is selected, the root node is used): t L'exemple suivant utilise les composants arbres par défaut pour afficher un arbre dans une applet. Lorsqu'on appuie sur le bouton, un nouveau sous-arbre est ajouté sous le noeud sélectionné (si aucun noeud n'est sélectionné, le noeud racine est utilisé) :
t t t
//: c13:Trees.java
// Simple Swing tree example. Trees can
// be made vastly more complex than this.
// <applet code=Trees
//  width=250 height=250></applet>
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.tree.*;
import com.bruceeckel.swing.*;

// Takes an array of Strings and makes the first
// element a node and the rest leaves:
class Branch {
  DefaultMutableTreeNode r;
  public Branch(String[] data) {
    r = new DefaultMutableTreeNode(data[0]);
    for(int i = 1; i < data.length; i++)
      r.add(new DefaultMutableTreeNode(data[i]));
  }
  public DefaultMutableTreeNode node() {
    return r;
  }
}  

public class Trees extends JApplet {
  String[][] data = {
    { "Colors", "Red", "Blue", "Green" },
    { "Flavors", "Tart", "Sweet", "Bland" },
    { "Length", "Short", "Medium", "Long" },
    { "Volume", "High", "Medium", "Low" },
    { "Temperature", "High", "Medium", "Low" },
    { "Intensity", "High", "Medium", "Low" },
  };
  static int i = 0;
  DefaultMutableTreeNode root, child, chosen;
  JTree tree;
  DefaultTreeModel model;
  public void init() {
    Container cp = getContentPane();
    root = new DefaultMutableTreeNode("root");
    tree = new JTree(root);
    // Add it and make it take care of scrolling:
    cp.add(new JScrollPane(tree),
      BorderLayout.CENTER);
    // Capture the tree's model:
    model =(DefaultTreeModel)tree.getModel();
    JButton test = new JButton("Press me");
    test.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e){
        if(i < data.length) {
          child = new Branch(data[i++]).node();
          // What's the last one you clicked?
          chosen = (DefaultMutableTreeNode)
            tree.getLastSelectedPathComponent();
          if(chosen == null) chosen = root;
          // The model will create the
          // appropriate event. In response, the
          // tree will update itself:
          model.insertNodeInto(child, chosen, 0);
          // This puts the new node on the
          // currently chosen node.
        }
      }
    });
    // Change the button's colors:
    test.setBackground(Color.blue);
    test.setForeground(Color.white);
    JPanel p = new JPanel();
    p.add(test);
    cp.add(p, BorderLayout.SOUTH);
  }
  public static void main(String[] args) {
    Console.run(new Trees(), 250, 250);
  }
} ///:~
t
//: c13:Trees.java
// Exemple d'arbre Swing simple. Les arbres peuvent
// être beaucoup plus complexes que celui-ci.
// <applet code=Trees
//  width=250 height=250></applet>
importjavax.swing.*;
importjava.awt.*;
importjava.awt.event.*;
importjavax.swing.tree.*;
importcom.bruceeckel.swing.*;

// Prend un tableau de Strings et crée un noeud à partir
// du premier élément, et des feuilles avec les autres :
classBranch {
DefaultMutableTreeNode r;
publicBranch(String[] data) {
   r = newDefaultMutableTreeNode(data[0]);
   for(inti = 1; i < data.length; i++)
     r.add(newDefaultMutableTreeNode(data[i]));
}
publicDefaultMutableTreeNode node() {
   returnr;
}
}  

publicclassTrees extendsJApplet {
String[][] data = {
   { "Colors", "Red", "Blue", "Green"},
   { "Flavors", "Tart", "Sweet", "Bland"},
   { "Length", "Short", "Medium", "Long"},
   { "Volume", "High", "Medium", "Low"},
   { "Temperature", "High", "Medium", "Low"},
   { "Intensity", "High", "Medium", "Low"},
};
staticinti = 0;
DefaultMutableTreeNode root, child, chosen;
JTree tree;
DefaultTreeModel model;
publicvoidinit() {
   Container cp = getContentPane();
   root = newDefaultMutableTreeNode("root");
   tree = newJTree(root);
   // On l'ajoute et on le rend scrollable :
   cp.add(newJScrollPane(tree),
     BorderLayout.CENTER);
   // Obtention du modèle de l'arbre :
   model =(DefaultTreeModel)tree.getModel();
   JButton test = newJButton("Press me");
   test.addActionListener(newActionListener() {
     publicvoidactionPerformed(ActionEvent e){
       if(i < data.length) {
         child = newBranch(data[i++]).node();
         // Quel est le dernier élément cliqué ?
         chosen = (DefaultMutableTreeNode)
           tree.getLastSelectedPathComponent();
         if(chosen ==null) chosen = root;
         // Le modèle créera l'événement approprié.
         // En réponse, l'arbre se remettra à jour :
         model.insertNodeInto(child, chosen, 0);
         // Ceci place le nouveau noeud
         // sur le noeud actuellement sélectionné.
       }
     }
   });
   // Change les couleurs des boutons :
   test.setBackground(Color.blue);
   test.setForeground(Color.white);
   JPanel p = newJPanel();
   p.add(test);
   cp.add(p, BorderLayout.SOUTH);
}
publicstaticvoidmain(String[] args) {
   Console.run(newTrees(), 250, 250);
}
} ///:~
t t t
The first class, Branch, is a tool to take an array of String and build a DefaultMutableTreeNode with the first String as the root and the rest of the Strings in the array as leaves. Then node( ) can be called to produce the root of this “branch.” t La première classe, Branch, est un outil qui prend un tableau et construit un DefaultMutableTreeNodeavec la première String comme racine, et le reste des Strings du tableau pour les feuilles. Ensuite node() peut être appelé pour créer la racine de cette branche.
t t t
The Trees class contains a two-dimensional array of Strings from which Branches can be made and a static int i to count through this array. The DefaultMutableTreeNode objects hold the nodes, but the physical representation on screen is controlled by the JTree and its associated model, the DefaultTreeModel. Note that when the JTree is added to the applet, it is wrapped in a JScrollPane—this is all it takes to provide automatic scrolling. t La classe Trees contient un tableau de Strings à deux dimensions à partir duquel des Branches peuvent être créées, ainsi qu'un static int i pour servir d'index à travers ce tableau. L'objet DefaultMutableTreeNode contient les noeuds, mais la représentation physique à l'écran est contrôlée par le JTree et son modèle associé, le DefaultTreeModel. Notons que lorsque le JTree est ajouté à l'applet, il est encapsulé dans un JScrollPane : c'est suffisant pour permettre un scrolling automatique.
t t t
The JTree is controlled through its model. When you make a change to the model, the model generates an event that causes the JTree to perform any necessary updates to the visible representation of the tree. In init( ), the model is captured by calling getModel( ). When the button is pressed, a new “branch” is created. Then the currently selected component is found (or the root is used if nothing is selected) and the model’s insertNodeInto( ) method does all the work of changing the tree and causing it to be updated. t Le JTree est contrôlé par son modèle. Lorsqu'on modifie les données du modèle, celui-ci génère un événement qui force le JTree à effectuer les mises à jour nécessaires de la partie visible de la représentation de l'arbre. Dans init(), le modèle est obtenu par appel à getModel(). Lorsqu'on appuie sur le bouton, une nouvelle branche est créée. Ensuite le composant actuellement sélectionné est recherché (on utilise la racine si rien n'est sélectionné) et la méthode insertNodeInto() du modèle effectue la modification de l'arbre et provoque sa mise à jour.
t t t
An example like the one above may give you what you need in a tree. However, trees have the power to do just about anything you can imagine—everywhere you see the word “default” in the example above, you can substitute your own class to get different behavior. But beware: almost all of these classes have a large interface, so you could spend a lot of time struggling to understand the intricacies of trees. Despite this, it’s a good design and the alternatives are usually much worse. t Un exemple comme ci-dessus peut vous donner ce dont vous avez besoin pour utiliser un arbre. Cependant les arbres ont la possibilité de faire à peu près tout ce qui est imaginable ; chaque fois que le mot default apparaît dans l'exemple ci-dessus, on peut y substituer sa propre classe pour obtenir un comportement différent. Mais attention : la plupart de ces classes a une interface importante, de sorte qu'on risque de passer du temps à comprendre la complexité des arbres. Cependant, on a affaire ici à une bonne conception, et les autres solutions sont en général bien moins bonnes.
t t t

Tables

t

Tables

t t t
Like trees, tables in Swing are vast and powerful. They are primarily intended to be the popular “grid” interface to databases via Java Database Connectivity (JDBC, discussed in Chapter 15) and thus they have a tremendous amount of flexibility, which you pay for in complexity. There’s easily enough here to be the basis of a full-blown spreadsheet and could probably justify an entire book. However, it is also possible to create a relatively simple JTable if you understand the basics. t Comme les arbres, les tables en Swing sont vastes et puissantes. Elles sont destinées principalement à être la populaire grille d'interface avec les bases de données via la Connectivité Bases de Données Java : Java DataBase Connectivity (JDBC, présenté dans le Chapitre 15) et pour cela elles ont une flexibilité énorme, que l'on paie en complexité. Il y a ici suffisamment pour servir de base à un tableur complet et pourrait probablement être le sujet d'un livre complet. Cependant, il est également possible de créer une name="Index1768">JTablerelativement simple si on en comprend les bases.
t t t
The JTable controls how the data is displayed, but the TableModel controls the data itself. So to create a JTable you’ll typically create a TableModel first. You can fully implement the TableModel interface, but it’s usually simpler to inherit from the helper class AbstractTableModel: t La JTable contrôle la façon dont les données sont affichées, tandis que le TableModel contrôle les données elles-mêmes. Donc pour créer une JTable on créera d'abord un TableModel. On peut implémenter complètement l'interface TableModel, mais il est souvent plus simple d'hériter de la classe utilitaire AbstractTableModel :
t t t
//: c13:Table.java
// Simple demonstration of JTable.
// <applet code=Table
//  width=350 height=200></applet>
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.table.*;
import javax.swing.event.*;
import com.bruceeckel.swing.*;

public class Table extends JApplet {
  JTextArea txt = new JTextArea(4, 20);
  // The TableModel controls all the data:
  class DataModel extends AbstractTableModel {
    Object[][] data = {
      {"one", "two", "three", "four"},
      {"five", "six", "seven", "eight"},
      {"nine", "ten", "eleven", "twelve"},
    };
    // Prints data when table changes:
    class TML implements TableModelListener {
      public void tableChanged(TableModelEvent e){
        txt.setText(""); // Clear it
        for(int i = 0; i < data.length; i++) {
          for(int j = 0; j < data[0].length; j++)
            txt.append(data[i][j] + " ");
          txt.append("\n");
        }
      }
    }
    public DataModel() {
      addTableModelListener(new TML());
    }
    public int getColumnCount() {
      return data[0].length;
    }
    public int getRowCount() {
      return data.length;
    }
    public Object getValueAt(int row, int col) {
      return data[row][col];
    }
    public void
    setValueAt(Object val, int row, int col) {
      data[row][col] = val;
      // Indicate the change has happened:
      fireTableDataChanged();
    }
    public boolean
    isCellEditable(int row, int col) {
      return true;
    }
  }
  public void init() {
    Container cp = getContentPane();
    JTable table = new JTable(new DataModel());
    cp.add(new JScrollPane(table));
    cp.add(BorderLayout.SOUTH, txt);
  }
  public static void main(String[] args) {
    Console.run(new Table(), 350, 200);
  }
} ///:~
t
//: c13:Table.java
// Démonstration simple d'une JTable.
// <applet code=Table
//  width=350 height=200></applet>
importjavax.swing.*;
importjava.awt.*;
importjava.awt.event.*;
importjavax.swing.table.*;
importjavax.swing.event.*;
importcom.bruceeckel.swing.*;

publicclassTable extendsJApplet {
JTextArea txt = newJTextArea(4, 20);
// Le TableModel contrôle toutes les données :
classDataModel extendsAbstractTableModel {
   Object[][] data = {
     {"one", "two", "three", "four"},
     {"five", "six", "seven", "eight"},
     {"nine", "ten", "eleven", "twelve"},
   };
   // Imprime les données lorsque la table change :
   classTML implementsTableModelListener {
     publicvoidtableChanged(TableModelEvent e){
       txt.setText(""); // Vider le texte
       for(inti = 0; i < data.length; i++) {
         for(intj = 0; j < data[0].length; j++)
           txt.append(data[i][j] + " ");
         txt.append("\n");
       }
     }
   }
   publicDataModel() {
     addTableModelListener(newTML());
   }
   publicintgetColumnCount() {
     returndata[0].length;
   }
   publicintgetRowCount() {
     returndata.length;
   }
   publicObject getValueAt(introw, intcol) {
     returndata[row][col];
   }
   publicvoid
   setValueAt(Object val, introw, intcol) {
     data[row][col] = val;
     // Indique que le changement a eu lieu :
     fireTableDataChanged();
   }
   publicboolean
   isCellEditable(introw, intcol) {
     returntrue;
   }
}
publicvoidinit() {
   Container cp = getContentPane();
   JTable table = newJTable(newDataModel());
   cp.add(newJScrollPane(table));
   cp.add(BorderLayout.SOUTH, txt);
}
publicstaticvoidmain(String[] args) {
   Console.run(newTable(), 350, 200);
}
} ///:~
t t t
DataModel contains an array of data, but you could also get the data from some other source such as a database. The constructor adds a TableModelListener that prints the array every time the table is changed. The rest of the methods follow the Beans naming convention, and are used by JTable when it wants to present the information in DataModel. AbstractTableModel provides default methods for setValueAt( ) and isCellEditable( ) that prevent changes to the data, so if you want to be able to edit the data, you must override these methods. t DataModelcontient un tableau de données, mais on pourrait aussi obtenir les données depuis une autre source telle qu'une base de données. Le constructeur ajoute un TableModelListener qui imprime le tableau chaque fois que la table est modifiée. Les autres méthodes suivent les conventions de nommage des Beans ; elles sont utilisées par la JTable lorsqu'elle veut présenter les informations contenues dans DataModel. AbstractTableModel fournit des méthodes par défaut pour setValueAt() et isCellEditable() qui interdisent les modifications de données, de sorte que ces méthodes devront être redéfinies si on veut pouvoir modifier les données.
t t t
Once you have a TableModel, you only need to hand it to the JTable constructor. All the details of displaying, editing, and updating will be taken care of for you. This example also puts the JTable in a JScrollPane. t Une fois obtenu un TableModel, il suffit de le passer au constructeur de la JTable. Tous les détails concernant l'affichage, les modifications et la mise à jour seront automatiquement gérés. Cet exemple place également la JTable dans un JScrollPane.
t t t

Selecting Look & Feel

t

Sélection de l'aspect de l'interface [Look & Feel]

t t t
One of the very interesting aspects of Swing is the “Pluggable Look & Feel.” This allows your program to emulate the look and feel of various operating environments. You can even do all sorts of fancy things like dynamically changing the look and feel while the program is executing. However, you generally just want to do one of two things, either select the “cross platform” look and feel (which is Swing’s “metal”), or select the look and feel for the system you are currently on, so your Java program looks like it was created specifically for that system. The code to select either of these behaviors is quite simple—but you must execute it before you create any visual components, because the components will be made based on the current look and feel and will not be changed just because you happen to change the look and feel midway during the program (that process is more complicated and uncommon, and is relegated to Swing-specific books). t Un des aspects très intéressants de Swing est le name="Index1770">Pluggable Look & Feel. Il permet à un programme d'émuler le look and feel de divers environnements d'exploitation. On peut même faire toutes sortes de choses comme par exemple changer le look and feel pendant l'exécution du programme. Toutefois, en général on désire soit sélectionner le look and feel toutes plateformes (qui est le Metal de Swing), soit sélectionner le look and feel du système courant, de sorte à donner l'impression que le programme Java a été créé spécifiquement pour ce système. Le code permettant de sélectionner chacun de ces comportements est assez simple, mais il faut l'exécuter avant de créer les composants visuels, car ceux-ci seront créés selon le look and feel courant et ne seront pas changés par le simple changement de look and feel au milieu du programme (ce processus est compliqué et peu banal, et nous en laisserons le développement à des livres spécifiques sur Swing).
t t t
Actually, if you want to use the cross-platform (“metal”) look and feel that is characteristic of Swing programs, you don’t have to do anything—it’s the default. But if you want instead to use the current operating environment’s look and feel, you just insert the following code, typically at the beginning of your main( ) but somehow before any components are added: t En fait, si on veut utiliser le look and feel toutes plateformes (metal) qui est la caractéristique des programmes Swing, il n'y a rien de particulier à faire, c'est la valeur par défaut. Si au contraire on veut utiliser le look and feel de l'environnement d'exploitation courant, il suffit d'insérer le code suivant, normalement au début du main() mais de toutes façons avant d'ajouter des composants :
t t t
try {
  UIManager.setLookAndFeel(UIManager.
    getSystemLookAndFeelClassName());
} catch(Exception e) {}
t
try{
UIManager.setLookAndFeel(UIManager.
   getSystemLookAndFeelClassName());
} catch(Exception e) {}
t t t
You don’t need anything in the catch clause because the UIManager will default to the cross-platform look and feel if your attempts to set up any of the alternatives fail. However, during debugging the exception can be quite useful so you may at least want to put a print statement in the catch clause. t Il n'y a pas besoin de faire quoi que ce soit dans la clause catch car le UIManager se positionnera par défaut au look and feel toutes plateformes si votre tentative d'installation d'un des autres échoue. Toutefois, pour le debug, l'exception peut être utile, de sorte qu'on peut au minimum placer une instruction d'impression dans la clause catch.
t t t
Here is a program that takes a command-line argument to select a look and feel, and shows how several different components look under the chosen look and feel: t Voici un programme qui utilise un argument de ligne de commande pour sélectionner un look and feel, et montre à quoi ressemblent différents composants dans le look and feel choisi :
t t t
//: c13:LookAndFeel.java
// Selecting different looks & feels.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import com.bruceeckel.swing.*;

public class LookAndFeel extends JFrame {
  String[] choices = {
    "eeny", "meeny", "minie", "moe", "toe", "you"
  };
  Component[] samples = {
    new JButton("JButton"),
    new JTextField("JTextField"),
    new JLabel("JLabel"),
    new JCheckBox("JCheckBox"),
    new JRadioButton("Radio"),
    new JComboBox(choices),
    new JList(choices),
  };
  public LookAndFeel() {
    super("Look And Feel");
    Container cp = getContentPane();
    cp.setLayout(new FlowLayout());
    for(int i = 0; i < samples.length; i++)
      cp.add(samples[i]);
  }
  private static void usageError() {
    System.out.println(
      "Usage:LookAndFeel [cross|system|motif]");
    System.exit(1);
  }
  public static void main(String[] args) {
    if(args.length == 0) usageError();
    if(args[0].equals("cross")) {
      try {
        UIManager.setLookAndFeel(UIManager.
          getCrossPlatformLookAndFeelClassName());
      } catch(Exception e) {
          e.printStackTrace(System.err);
      }
    } else if(args[0].equals("system")) {
      try {
        UIManager.setLookAndFeel(UIManager.
          getSystemLookAndFeelClassName());
      } catch(Exception e) {
          e.printStackTrace(System.err);
      }
    } else if(args[0].equals("motif")) {
      try {
        UIManager.setLookAndFeel("com.sun.java."+
          "swing.plaf.motif.MotifLookAndFeel");
      } catch(Exception e) {
          e.printStackTrace(System.err);
      }
    } else usageError();
    // Note the look & feel must be set before
    // any components are created.
    Console.run(new LookAndFeel(), 300, 200);
  }
} ///:~
t
//: c13:LookAndFeel.java
// Sélection de divers looks & feels.
importjavax.swing.*;
importjava.awt.*;
importjava.awt.event.*;
importjava.util.*;
importcom.bruceeckel.swing.*;

publicclassLookAndFeel extendsJFrame {
String[] choices = {
   "eeny", "meeny", "minie", "moe", "toe", "you"
};
Component[] samples = {
   newJButton("JButton"),
   newJTextField("JTextField"),
   newJLabel("JLabel"),
   newJCheckBox("JCheckBox"),
   newJRadioButton("Radio"),
   newJComboBox(choices),
   newJList(choices),
};
publicLookAndFeel() {
   super("Look And Feel");
   Container cp = getContentPane();
   cp.setLayout(newFlowLayout());
   for(inti = 0; i < samples.length; i++)
     cp.add(samples[i]);
}
privatestaticvoidusageError() {
   System.out.println(
     "Usage:LookAndFeel [cross|system|motif]");
   System.exit(1);
}
publicstaticvoidmain(String[] args) {
   if(args.length == 0) usageError();
   if(args[0].equals("cross")) {
     try{
       UIManager.setLookAndFeel(UIManager.
         getCrossPlatformLookAndFeelClassName());
     } catch(Exception e) {
         e.printStackTrace(System.err);
     }
   } elseif(args[0].equals("system")) {
     try{
       UIManager.setLookAndFeel(UIManager.
         getSystemLookAndFeelClassName());
     } catch(Exception e) {
         e.printStackTrace(System.err);
     }
   } elseif(args[0].equals("motif")) {
     try{
       UIManager.setLookAndFeel("com.sun.java."+
         "swing.plaf.motif.MotifLookAndFeel");
     } catch(Exception e) {
         e.printStackTrace(System.err);
     }
   } elseusageError();
   // Remarquons que le look & feel doit être positionné
   // avant la création des composants.
   Console.run(newLookAndFeel(), 300, 200);
}
} ///:~
t t t
t t t
t t
\\\
///
t t t
t
     
Sommaire Le site de Bruce Eckel