C.
RECANATI
IHM Java
Swing
TP n¡ 7
Exercice 1: (suite de l’ex.2, TP 6 : Sketcher comme
logiciel de dessin).
On va garder
provisoirement le JTextArea
pour afficher des informations sur les événements, mais, à
terme, on le supprimera pour dessiner dans la fenêtre.
Les items du menu
Elements permettent de sélectionner la couleur et le type de
l’élément (la forme) que l’on souhaite dessiner. On
rajoute donc deux nouveaux membres à la classe SketcherFrame : elementColor de type Color et elementType de type entier. Ces membres seront mis à jour quand on
sélectionnera les options du menu Elements.
Pour que les
initialisations soient claires et faciles à modifier, on définit
dans un fichier séparé une interface Constants qui définit les types
d’éléments entiers LIGNE, RECTANGLE, CERCLE, COURBE et les conditions initiales des
membres elementType et elementColor ( DEFAULT_ELEMENT_TYPE et DEFAULT_ELEMENT_COLOR). La classe SketcherFrame implémentera
l’interface Constants et se servira de ces constantes pour
faire les initialisations.
1) Définir
l’interface Constants et
modifier la création des cases à cocher du sous-menu Couleurs pour que la case à cocher
marquée initialement corresponde à la couleur de défaut
initiale . Modifier également la création des boutons radio pour
qu’ils soient sélectionnés au départ
conformément au type initial de elementType.
2) Pour
gérer les types d’options du menu Elements, définir une
classe interne TypeListener qui
implémente ActionListener
et comporte un membre privé type permettant de stocker le type de l’élément
écouté. Cette classe aura un constructeur qui prend en argument
le type et le mémorise dans son champs privé type. Cela permettra d’adapter les
écouteurs aux différents items du menu Elements à leur
création. Lorsqu’une option du menu sera activée,
l’écouteur consultera son type privé et mettra elementType à jour.
3) On
procèdera de même pour gérer la couleur en
implémentant une classe interne ColorListener qui comportera un membre privé color permettant de définir la couleur
de l’élément écouté.
4) Ajouter des
écouteurs anonymes aux boutons de la ToolBar (‘anonymes’
signifie qu’on définit l’écouteur directement au
moment où on l’ajoute, sans le nommer) pour afficher
dans le JTextArea quel bouton (gauche, milieu, ou droit) a
été enfoncé.
Correction
Exercice
1
// fichier
Sketcher.java
import java.awt.*;
public class Sketcher {
static SketcherFrame window;
public static void main(String[] args) {
window
= new SketcherFrame("Sketcher");
Toolkit
leKit = window.getToolkit();
Dimension
wndSize = leKit.getScreenSize();
window.setBounds(wndSize.width/4,
wndSize.height/4,
wndSize.width/2,
wndSize.height/2);
window.setVisible(true);
}
}
// fichier
Constants.java
import java.awt.*;
public interface Constants {
// Les types
d'élements
int LIGNE = 101;
int RECTANGLE = 102;
int CERCLE = 103;
int COURBE = 104;
// Les
conditions initiales
int DEFAULT_ELEMENT_TYPE = RECTANGLE;
Color DEFAULT_ELEMENT_COLOR = Color.green;
}
//
fichier SketcherFrame.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SketcherFrame extends JFrame
implements
constants {
protected
JTextArea output ;
protected
JScrollPane scrollPane;
private
JMenuBar menuBar;
private
Color elementColor =
DEFAULT_ELEMENT_COLOR ;
private
int elementType = DEFAULT_ELEMENT_TYPE;
protected
String newline = "\n";
public
SketcherFrame(String titre) {
JMenu
menu, submenu;
JMenuItem
menuItem;
JRadioButtonMenuItem
rbMenuItem;
JCheckBoxMenuItem
cbMenuItem;
setTitle(titre);
setDefaultCloseOperation(EXIT_ON_CLOSE);
//Créer
la toolbar.
JToolBar
toolBar = new JToolBar();
toolBar.setFloatable(false);
addButtons(toolBar);
//
etc. début de la construction inchangé
// Construire le menu Elements
…
menu
= new JMenu("Elements");
menu.setMnemonic(KeyEvent.VK_E);
menuBar.add(menu);
ButtonGroup
group = new ButtonGroup();
rbMenuItem
= new JRadioButtonMenuItem("Ligne",
elementType
== LIGNE);
rbMenuItem.setMnemonic(KeyEvent.VK_L);
group.add(rbMenuItem);
rbMenuItem.addActionListener(new
TypeListener(LIGNE));
menu.add(rbMenuItem);
rbMenuItem
= new JRadioButtonMenuItem
("Rectangle",
elementType
== RECTANGLE);
rbMenuItem.setMnemonic(KeyEvent.VK_R);
group.add(rbMenuItem);
rbMenuItem.addActionListener
(new
TypeListener(RECTANGLE));
menu.add(rbMenuItem);
//
etc. pour les autres types de formes
menu.addSeparator();
submenu
= new JMenu("Couleur");
submenu.setMnemonic(KeyEvent.VK_C);
//
le groupe de check box menu items
ButtonGroup
group2 = new ButtonGroup();
cbMenuItem
= new JCheckBoxMenuItem("Rouge",
elementColor.equals(Color.red));
cbMenuItem.setMnemonic(KeyEvent.VK_R);
group2.add(cbMenuItem);
cbMenuItem.addActionListener
(new
ColorListener(Color.red));
submenu.add(cbMenuItem);
//
etc. pour bleu, vert, etc.
//Construire
le menu Aide
//
fin du constructeur
}
class
TypeListener implements ActionListener {
private
int type;
TypeListener(int
type) {
this.type
= type; // mémorise le
type
}
public
void actionPerformed(ActionEvent e) {
elementType
= type; // l’essentiel !
JMenuItem
source
=
(JMenuItem)(e.getSource());
String
s = "ActionEvent detecte dans
\TypeListener."
+
newline
+
" Event source:
"
+
source.getText()
+
" (une instance de "
+
getClassName(source) + ")";
output.append(s
+ newline);
}
}
class
ColorListener implements ActionListener {
private
Color color;
ColorListener(Color
color) {
this.color
= color; // mémorise
color
}
public
void actionPerformed(ActionEvent e) {
elementColor
= color; // l’essentiel !
JMenuItem
source =
(JMenuItem)(e.getSource());
String
s = "ActionEvent detecte dans
\ ColorListener."
+
newline
+
" Event source:
"
+
source.getText()
+
" (une instance de "
+
getClassName(source) + ")";
output.append(s
+ newline);
}
}
// Retourne juste le nom de la classe
protected
String getClassName(Object o) {
String
classString = o.getClass().getName();
int
dotIndex = classString.lastIndexOf(".");
return
classString.substring(dotIndex+1);
}
protected
void addButtons(JToolBar toolBar) {
JButton
button = null;
//
premier bouton
button
= new JButton(new
ImageIcon("images/left.gif"));
button.setToolTipText("bouton
de gauche");
button.addActionListener(new
ActionListener() {
public
void actionPerformed
(ActionEvent
e){
displayResult("ActionEvent
bouton1");
}
});
toolBar.add(button);
// ibid deuxieme et
troisieme boutons
}
protected
void displayResult
(String
actionDescription) {
output.append(actionDescription
+ newline);
}
}
Exercice
2 :
On
va créer un JApplet qui présente une liste scrollée dans sa
partie centrale et au dessus, deux boutons alignés horizontalement
permettant respectivement :
1.
de détruire les items
sélectionnés dans la liste et
2.
d’ajouter un item à la liste.
1)
Compléter pour cela le squelette de programme suivant
:
public class Test extends JApplet {
private
JList list = new JList();
String[]
items = { "item[0]", "item[1]", "item[2]",
"item[3]", "item[4]",
"item[5]",
"item[6]",
"item[7]", "item[8]", "item[9]"
};
public
void init() {
Container
contentPane = getContentPane();
ControlPanel
controlPanel = new ControlPanel(list);
// défini plus loin
contentPane.add(controlPanel,
BorderLayout.NORTH);
contentPane.add(new
JScrollPane(list), BorderLayout.CENTER);
populateList();
}
public
void populateList() {
//
construire un modèle à partir de
DefaultListModel
//
l’initialiser avec le tableau d’items et l’affecter à
la liste privée
}
}
class ControlPanel extends JPanel {
private
JButton remove = new JButton("supprimer la
selection");
private
JButton add = new JButton("ajouter un item");
private
JList list ;
public
ControlPanel(JList ls) {
this.list
= ls ;
add(remove);
add(add);
remove.addActionListener(new
ActionListener() {
public
void actionPerformed(ActionEvent e) {
//
récupérer les indices sélectionnés de la
liste
//
et récupérer le modèle
//
puis supprimer les items correspondants du modèle
}
}
});
add.addActionListener(new
ActionListener() {
public
void actionPerformed(ActionEvent e) {
//
récupérer le modèle de la liste
//
récupérer la chaîne (l’item) à
rajouter dans
//
une boîte de dialogue modale
//
l’ajouter au modèle
SwingUtilities.invokeLater(new
Runnable() {
public
void run() {
list.ensureIndexIsVisible(
model.getSize()-1);
}
});
}
});
}
}
Remarque :
grâce à invokeLater, la procédure ensureIndexIsVisible ne sera effectuée qu’après que les
événements de mise à jour aient été
traités.
2)
On rajoute au panneau de contrôle une JComboBox
présentant le mode de sélection utilisée par la liste,
soit : SINGLE_SELECTION,
SINGLE_INTERVAL_SELECTION, MULTIPLE_INTERVAL_SELECTION. On écrira une procédure
privée initializeSelectionMode() qui initialise l’item
sélectionné de la comboBox conformément au mode de
sélection initial de la liste, et on ajoutera un ItemListener à la comboBox pour mettre à jour le
mode de sélection de la liste quand un nouveau mode est
sélectionné sur la comboBox.
3)
Modifier encore le panneau de contrôle ControlPanel
pour qu’il affiche sous les boutons précédents:
1.
les indices des items sélectionnés dans la liste (sous une forme
comme : ‘Items sélectionnés : 3, 4, 5,
9 ‘
réalisée avec deux labels disposés
horizontalement) ;
2.
au dessous les indices minimum et maximum des items sélectionnés.
Pour la mise à jour de ces labels, on écrira une
méthode update() pour le panneau de contrôle qui sera
appelée quand la sélection de la liste change (utiliser
un ListSelectionListener sur la liste).
Indication :
pour le placement des composants dans le ControlPanel, on
pourra utiliser trois JPanel et un BoxLayout vertical.
Le JPanel du haut servira à placer les boutons et la
comboBox, celui du milieu les labels des indices sélectionnés, et
celui du dessous les labels des indices minimum et
maximum.
Correction
import
java.awt.*;
import
java.awt.event.*;
import
javax.swing.*;
import
javax.swing.event.*;
public
class Test2 extends JApplet {
private
JList list = new JList();
String[]
items = { "item[0]", "item[1]",
"item[2]",
"item[3]",
"item[4]", "item[5]",
"item[6]",
"item[7]",
"item[8]",
"item[9]" };
public
void init() {
Container
contentPane = getContentPane();
ControlPanel
controlPanel = new ControlPanel(list);
contentPane.add(controlPanel,
BorderLayout.NORTH);
contentPane.add(new
JScrollPane(list), BorderLayout.CENTER);
populateList();
controlPanel.update()
;
}
public
void populateList() {
DefaultListModel
model = new DefaultListModel();
for(int
i=0; i < items.length; ++i)
model.addElement(items[i]);
list.setModel(model);
}
}
class
ControlPanel extends JPanel {
JButton
remove = new JButton("supprimer la selection");
JButton
add = new JButton("ajouter un item");
private
JComboBox mode = new JComboBox();
private
JList list;
private
String single = "SINGLE_SELECTION",
singleInterval =
"SINGLE_INTERVAL_SELECTION",
multipleInterval =
"MULTIPLE_INTERVAL_SELECTION";
private
JLabel minLabel = new JLabel(),
maxLabel = new
JLabel(),
selIndicesLabel = new
JLabel();
public
ControlPanel(JList lis) {
JPanel
top = new JPanel(),
mid = new
JPanel(),
bottom = new
JPanel();
this.list
= lis;
setLayout(new
BoxLayout(this, BoxLayout.Y_AXIS));
setBorder(BorderFactory.createEtchedBorder());
top.add(remove);
top.add(add);
top.add(mode);
mode.addItem(single);
mode.addItem(singleInterval);
mode.addItem(multipleInterval);
initializeSelectionMode();
mid.add(new
JLabel("Minimum:"));
mid.add(minLabel);
mid.add(new
JLabel("Maximum:"));
mid.add(maxLabel);
add(top);
add(mid);
add(bottom);
bottom.add(new
JLabel("Indices selectionnes:"));
bottom.add(selIndicesLabel);
remove.addActionListener(new
ActionListener() {
public
void actionPerformed(ActionEvent e) {
int[]
selected = list.getSelectedIndices();
DefaultListModel
model =
(DefaultListModel)list.getModel();
for(int
i=0; i < selected.length; ++i) {
model.removeElementAt(selected[i]
- i);
}
}
});
add.addActionListener(new
ActionListener() {
public
void actionPerformed(ActionEvent e) {
final
DefaultListModel model =
(DefaultListModel)list.getModel();
String
s = JOptionPane.showInputDialog(
list,
"Entrer
un item : ");
model.addElement(s);
SwingUtilities.invokeLater(new
Runnable() {
public
void run() {
list.ensureIndexIsVisible(
model.getSize()-1);
}
});
}
});
mode.addItemListener(new
ItemListener() {
public
void itemStateChanged(ItemEvent e) {
if(e.getStateChange()
== ItemEvent.SELECTED) {
setSelectionMode((String)e.getItem());
}
}
});
list.addListSelectionListener(
new ListSelectionListener() {
public
void valueChanged(ListSelectionEvent e) {
update();
}
});
}
public
void update() {
int
min =
list.getMinSelectionIndex(),
max
= list.getMaxSelectionIndex() ;
minLabel.setText(Integer.toString(min)
+ " / ");
maxLabel.setText(Integer.toString(max));
int[]
selected = list.getSelectedIndices();
String
s = new String();
for(int
i = 0; i < selected.length; ++i) {
s
+= Integer.toString(selected[i]);
if(i
< selected.length-1)
s
+= ",";
}
selIndicesLabel.setText(s);
validate();
}
private
void initializeSelectionMode() {
int
m = list.getSelectionMode();
switch(m)
{
case
ListSelectionModel.SINGLE_SELECTION:
mode.setSelectedItem(single);
break;
case
ListSelectionModel.SINGLE_INTERVAL_SELECTION:
mode.setSelectedItem(singleInterval);
break;
case
ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:
mode.setSelectedItem(multipleInterval);
break;
}
}
private
void setSelectionMode(String s) {
if(s.equals("SINGLE_SELECTION"))
{
System.out.println("single selected");
list.setSelectionMode(
ListSelectionModel.SINGLE_SELECTION);
}
else
if(s.equals("SINGLE_INTERVAL_SELECTION")) {
System.out.println("single interval
selected");
list.setSelectionMode(
ListSelectionModel.SINGLE_INTERVAL_SELECTION);
}
else
if(s.equals("MULTIPLE_INTERVAL_SELECTION")) {
System.out.println("multiple interval
selected");
list.setSelectionMode(
ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
}
}
}