Date de première publication : 2014/02/06
Nous allons faire un petit programme Swing avec animation. Je vous laisse découvrir la tête du résultat :
L'idée de base est de proposer une sorte de "beatbox" : les barres de progression représentent un signal. L'animation n'est effective que lorsque la barre de progression est activée par un bouton on/off.
Mise en place de l'interface
L'interface n'est donc composée que de boutons (les JButton
suffisent même s'il existe d'autres types de bouton) et une barre de progression.
La bibliothèque Swing propose deux composants mais un seul est vraiment adapté, pouvez-vous le retrouver grâce à la documentation ou au tutoriel ? Ne découvrez la zone suivante que si vous séchez vraiment :
[A] ProgressMonitor
[B] JProgressBar
[C] RTFM
[D] Obiwan Kenobi
Le plus difficile va être de faire la disposition, je vous laisse le choix des armes : un des éditeurs graphiques de votre EDI préféré ou le faire à la main... Dans ce dernier cas, vous avez le choix :
- Combiner différents panels
- Utiliser un
GridBagLayout
Evidemment, cet agencement dépend de la modélisation des composants mais nous en discuterons plus tard...
Petite remarque en passant, je n'ai pas réussi à utiliser le constructeur de la barre de progression où l'on spécifie à la fois l'orientation de la barre et la valeur maximale mais j'ai testé avec une bêta de java 8...
Version combinaison de panels
Si vous voulez une idée de combinaison de panels :
Je vous propose de prendre un JPanel avec BoxLayout pour mettre une barre de progression et le bouton. Il faut penser à mettre la Box en vertical
et fixer l'alignement horizontal des DEUX composants.
Il suffit ensuite de placer plusieurs composants dans un FlowLayout.
Version GridBagLayout
Pour info, voilà une réalisation avec un GridBagLayout
mais je n'irai pas plus loin dans l'explication...
GridBagLayout gbl = new GridBagLayout();
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.gridy = 0;
gbc.gridheight = 10;
// PLACEMENT DES BARRES DE PROGRESSION
for (int i = 0; i< 5 ; ++i) {
// jpb est une barre de progression
gbc.gridx = i;
gbc.gridwidth = i < 4 ? 1 : GridBagConstraints.REMAINDER;
gbl.setConstraints(jpb, gbc);
frame.getContentPane().add(jpb);
}
// PLACEMENT DES BOUTONS
gbc.gridy = 10;
gbc.gridheight = 1;
for (int i = 0; i< 5 ; ++i) {
// jb est un bouton
gbc.gridx = i;
gbc.gridwidth = i < 4 ? 1 : GridBagConstraints.REMAINDER;
gbl.setConstraints(jb, gbc);
frame.getContentPane().add(jb);
}
L'animation
Vous avez placé les composants. Nous allons maintenant animer les barres de progression.
Je vous propose de créer une tâche pour chaque barre de progression : la tâche aura pour mission de changer la valeur de la barre de progression,
d'attendre quelques millisecondes (Thread.sleep(n)
) et de recommencer ...
Pour plus de simplicité, je vous propose de créer une nouvelle classe de barre de progression qui soit à la fois capable
de réaliser une tâche (Runnable
)
et de répondre à l'appui sur un bouton (ActionListener
)
Ce que je propose de faire :
- Si la barre n'est pas active à l'appui sur un bouton, créer un nouveau thread, affecter la tâche
- Si la barre est activée, arrêter naturellement la méthode run() grâce à un état/drapeau.
Et voilà, cahier des charges rempli...
Vlà le facteur !
mais bon, au final, cela ne me semble pas très cohérent. Finalement, dans notre programme, on peut identifier un composant qui regroupe une barre de progression et un bouton...
Nous allons donc faire du refactoring sur notre application : améliorer le code / la conception sans introduire de nouvelle fonctionnalité.
Je vous propose de créer votre propre composant dérivant de JPanel qui agrège une barre de progression et un bouton. La solution de la disposition est alors naturelle et simple.