Java/Interfaces graphiques
Apparence
< Java
Interfaces
[modifier | modifier le wikicode]Différents packages peuvent assurer l'interface graphique :
- AWT.
- SWT.
- Swing, voir aussi le wikilivre sur Swing.
- JavaFX remplaçant Swing dans les versions récentes de Java.
Locode
[modifier | modifier le wikicode]Ceci est un petit programme qui télécharge la liste des codes de localisation de la Commission économique des Nations Unies pour l'Europe (UNECE) et affiche la table des codes de localisation avec une classe Tablesorter spécial publié par Oracle. La trieuse de table peut trier par plusieurs lignes (maintenez la touche CTRL et sélectionner une autre ligne en cliquant sur l'en-tête pour trier par un deuxième ou troisième rangée).
Code source
[modifier | modifier le wikicode]package org.wikiversity.java_tutorial;
import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ScrollPaneConstants;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import misc.oracle.components.TableSorter; // http://vsrs.svn.sourceforge.net/viewvc/vsrs/src/vsrs/ui/components/TableSorter.java
public class Locode
{
// Une constante pour la page internet.
public final static String LOCODE_URL = "http://live.unece.org/fileadmin/DAM/cefact/locode/loc111csv.zip";
// Un tableau pour la largeur des colonnes de la table.
private final static int[] WIDTH = {
50, 50, 50, 250, 250, 50, 120, 50, 120, 50, 250, 50
};
/**
* Le programme télécharge une liste des codes de localisation de la
* commission économique pour l'Europe.
* La principale méthode est toujours la première méthode appelée dans
* un programme et appelle toutes les autres méthodes.
*
* @see http://fr.wikipedia.org/wiki/Commission_économique_pour_l'Europe
* @param args
*/
public static void main (String[] args)
{
// En programmation orientée objet, une instance d'une classe est un objet
// avec un comportement correspondant à cette classe et un état initial.
// Le comportement de la classe est définie par ses méthodes.
new Locode ().run (args); // Créer une instance de la classe de Locode
}
/**
* Dans ce programme, la seule méthode appelée par
* les méthode «main» est «run».
* «run» est une méthode d'instance (sans le mot clé «static»)
*/
private void run (String[] args)
{
// Créer une instance de la classe de File.
File locodeArchive = file ("~/.un/locode/loc111csv.zip");
// Un appel à la méthode «mkdirs» dans une autre classe crée un dossier pour le fichier.
locodeArchive.getParentFile ().mkdirs ();
// Un appel à la méthode «downloadArchive» dans cette classe
// télécharge l'archive de la UNECE.
downloadArchive (locodeArchive);
// Test avec «IF», si l'archive existe maintenant
if (!locodeArchive.exists ())
{
// Ces deux déclarations ne sont exécutées que si l'archive n'existe pas.
System.err.println ("Archive " + LOCODE_URL + " is not available.");
// Mettre fin au programme: le programme a échoué
System.exit (1);
}
// Un appel à la méthode «readDataFromArchive» dans cette classe
// lit les données de l'archive.
DefaultTableModel model = readDataFromArchive (locodeArchive);
// Demandez à l'DefaultTableModel classe pour le nombre de lignes
// lues avec le méthode «getRowCount» et d'imprimer la valeur.
System.out.println (model.getRowCount () + " rows.");
// Un appel à la méthode «displayTable» dans cette classe
// affiche le tableau à l'écran.
displayTable (model);
}
/**
* Affiche le tableau à l'écran.
*
* @param model
*/
private void displayTable (DefaultTableModel model)
{
JFrame frame = new JFrame ("UN Location Codes");
frame.setDefaultCloseOperation (WindowConstants.EXIT_ON_CLOSE);
frame.setLayout (new BorderLayout ());
frame.setSize (1024, 500);
JTable table = new JTable ();
JScrollPane js = new JScrollPane (table);
js.setHorizontalScrollBarPolicy (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
js.setVerticalScrollBarPolicy (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
frame.add (js, BorderLayout.CENTER);
table.getTableHeader ().setReorderingAllowed (true);
table.getTableHeader ().setResizingAllowed (true);
TableSorter sorter = new TableSorter (model);
table.setModel (sorter);
sorter.setTableHeader (table.getTableHeader ());
for (int i=0; i<12; i++)
table.addColumn (new TableColumn (i, WIDTH[i]));
frame.setVisible (true);
}
private final static File file (String path)
{
if (path.charAt (0) == '~')
path = System.getProperty ("user.home") + path.substring (1);
return new File (path);
}
/**
* Télécharge l'archive de la UNECE.
*
* @param locodeArchive
*/
private void downloadArchive (File locodeArchive)
{
long lastModified = locodeArchive.lastModified ();
try {
URL url = new URL (LOCODE_URL);
URLConnection c = url.openConnection ();
if (c.getLastModified () <= lastModified)
return;
byte buffer[] = new byte[0xffff];
OutputStream os = null;
InputStream is = c.getInputStream ();
try
{
int bytesRead;
os = new FileOutputStream (locodeArchive);
for (;;)
{
if ((bytesRead = is.read (buffer)) == -1)
break;
os.write (buffer, 0, bytesRead);
System.out.print (".");
System.out.flush ();
}
System.out.println ();
}
catch (Exception ex) {
closeSilently (os);
closeSilently (is);
}
}
catch (Exception ex) {
System.err.println ("Failed to download file: " + ex);
}
}
/**
* Lit les données de l'archive.
*
* @param inputFile
* @return
*/
private DefaultTableModel readDataFromArchive (File inputFile)
{
DefaultTableModel model = new DefaultTableModel ();
Vector<Object> v = model.getDataVector ();
InputStream is = null;
JarFile file = null;
BufferedReader br;
String line, nextLine;
Object[] row;
try
{
// Créer une instance de la classe JarFile (jar fichier)
// pour le archive.
file = new JarFile (inputFile);
// Créer une énumération du contenu de l'archive
// et itérer sur l'énumération.
for (Enumeration<JarEntry> e = file.entries (); e.hasMoreElements (); )
{
// Créer une instance de la classe JarEntry (jar entrée)
// pour le archive.
JarEntry je = (JarEntry) e.nextElement ();
// Le «IF» tests si le nom du fichier se termine par "csv".
if (!je.getName ().toLowerCase ().endsWith (".csv"))
continue;
// Imprimer le nom de l'entrée.
System.out.println ("Reading: " + je.getName ());
// Demande une instance de la classe InputStream.
is = file.getInputStream (je);
// Créer une instance de la classe BufferedReader.
br = new BufferedReader (new InputStreamReader (is));
// Un bloc avec un nom permet référer à ce bloc dans
// une instruction break; l'instruction termine l'exécution
// de ce bloc et le programme se poursuit après la fin du bloc.
loop:
while ((line = br.readLine ()) != null)
{
// Un appel à la méthode «csvSplit».
row = csvSplit (line);
while (row.length < 12)
{
// Affiche un message indiquant que la ligne
// ne contient pas suffisamment de données
System.out.println ("Unexpected number of fields: " + row.length + ", reading next line for more input.");
// S'il n'ya pas d'entrée pour lire plus l'instruction «IF»
// se termine le bloc. Sans le nom il serait tout simplement
// mettre fin à la boucle while.
if ((nextLine = br.readLine ()) == null)
break loop;
// Ajoute les données de la ligne précédente à la ligne actuelle.
line += nextLine;
// Un appel à la méthode «csvSplit».
row = csvSplit (line);
// Un appel à la méthode «printRow» (ligne Imprimez)
printRow (line, row);
}
// Ajoute les ligne avec un appel à la méthode "addElement"
// à la classe Vector (vecteur, un type de tableau).
v.addElement (new Vector<Object> (Arrays.asList (row)));
}
}
}
catch (Exception ex) {
closeSilently ((Closeable) file);
closeSilently (is);
}
return model;
}
private void printRow (String line, Object[] row)
{
System.out.println ("---- " + line);
for (int i=0; i<row.length; i++)
{
System.out.println ("[" + i + "]: " + row[i]);
}
}
private void closeSilently (Closeable c)
{
if (c != null) {
try {
c.close ();
}
catch (IOException ex) { /* intentionally ignored */ }
}
}
private final static String[] STRING_ARRAY = new String[0];
/**
* La méthode divise une chaîne en un tableau de chaînes.
*
* @param s
* @return
*/
private final static String[] csvSplit (String s)
{
ArrayList<String> a = new ArrayList<String> ();
char[] chars = s.toCharArray ();
int p1 = 0, p2;
for (;;)
{
if ((p2 = csvIndexOf (chars, p1)) == -1) {
a.add (trimQuotes (s.substring (p1)));
break;
}
String sub = s.substring (p1, p2);
p1 = p2 + 1;
a.add (trimQuotes (sub));
}
if (a.size () == 0)
return STRING_ARRAY;
return (String[]) a.toArray (STRING_ARRAY);
}
/**
* La méthode supprime guillemets au début et à la fin d'une chaîne.
*
* @param s
* @return
*/
private final static String trimQuotes (String s)
{
if (s.startsWith ("\"") && s.endsWith ("\"")) {
return s.substring (1, s.length () - 1);
}
return s;
}
/**
* La méthode itère sur les caractères d'une chaîne commençant
* par le caractère à la position «pos» et retourne la virgule
* suivant qui n’est pas entre guillemets.
*
* @param str
* @param pos
* @return
*/
private final static int csvIndexOf (char[] str, int pos)
{
boolean notInsideQuote = true;
for (int i=pos; i<str.length; i++)
{
if (str[i] == '"')
notInsideQuote = !notInsideQuote;
if (str[i] == ',' && notInsideQuote)
return i;
}
return -1;
}
}
Exercices
[modifier | modifier le wikicode]- Améliorer le modèle de table et le rendu des cellules du tableau. Que peut-il être amélioré ?
- Ajouter un filtre qui permet de filtrer la table avec des expressions rationnelles.
- Affichage des codes d'emplacement sur un globe ou de permettre de sélectionner des régions sur une carte.