1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
| import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class Test extends JFrame {
private String[] genre = { " Masculin ", " Feminin " };
public Test() {
this.setTitle("Deplacement");
this.setSize(500, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.getContentPane().setLayout(null); // on n'utilise pas de Layout Manager
// on créé 2 tableaux pour stocker les composants, parce qu'on a besoin de leurs références pour les déplacer
JLabel[] labels = new JLabel[3];
JComponent[] fields = new JComponent[3];
labels[0] = new JLabel("Nom:");
fields[0] = new JTextField(10);
labels[1] = new JLabel("Prénom:");
fields[1] = new JTextField(10);
labels[2] = new JLabel("Sexe:");
fields[2] = new JComboBox<String>(genre);
// le fait qu'on ait des tableaux permet de gérer les composants en boucle
for(int i=0; i<3; i++) {
add(labels[i]);
add(fields[i]);
// on place et dimensionne les composants parce qu'il n'y a pas de Layout Manager qui le fait
labels[i].setSize(labels[i].getPreferredSize());
fields[i].setSize(fields[i].getPreferredSize());
if (i>0){
labels[i].setLocation(fields[i-1].getX()+fields[i-1].getWidth(), 0);
}
fields[i].setLocation(labels[i].getX()+labels[i].getWidth(), 0);
// on créé le MouseAdapter
MouseAdapter mouseAdapter = new MoveMouseAdapter(i, labels, fields);
labels[i].addMouseListener(mouseAdapter); // on enregistre le MouseAdapter comme MouseListener sur le label (pour détecter l'enfoncement et le relachement du bouton
labels[i].addMouseMotionListener(mouseAdapter); // on enregistre le MouseAdapter comme MouseMotionListener sur le label (pour détecter le mouvement de la souris)
}
this.setVisible(true);
}
public static void main(String[] main) {
new Test();
}
private static class MoveMouseAdapter extends MouseAdapter {
private boolean moved; // lorsque true, indique que le déplacement est en cours
private int dx; // décalage initial entre la position x de la souris et la position x du label déplacé
private int dy; // décalage initial entre la position y de la souris et la position y du label déplacé
private final JLabel label; // le label déplacé
private final JComponent field; // champ déplacé
private final int index; // numéro d'index du label déplacé
private final JLabel[] labels; // tableau des labels
private final JComponent[] fields; // tableau des champs
private Rectangle[] bounds; // contient les dimensions des label/fields autres que celui déplacé au démarrage du déplacement
private int startLocationX; // position x du label déplacé au démarrage (permettant de revenir à la position initiale)
private int startLocationY; // position y du label déplacé au démarrage (permettant de revenir à la position initiale)
private boolean overlayed; // lorsque true, indique qu'il y a eu superposition
public MoveMouseAdapter(int index, JLabel[] labels, JComponent[] fields) {
this.index=index;
this.label=labels[index];
this.field=fields[index];
this.labels=labels;
this.fields=fields;
}
@Override
public void mousePressed(MouseEvent e) {
if ( e.getButton()==MouseEvent.BUTTON1 ) { // sur le bouton gauche
startMove(e);
}
}
private void startMove(MouseEvent e) {
moved=true;
// on mémorise la position relative de la souris par rapport au composant
dx=e.getX();
dy=e.getY();
// on mémorise les bounds de tous les autres composants
bounds = getOtherComponentsBounds();
// on mémorise la position au démarrage
startLocationX=label.getX();
startLocationY=label.getY();
}
/*
* Mémorise les bounds de tous les couples label/fields autre que celui déplacé
*/
private Rectangle[] getOtherComponentsBounds() {
Rectangle[] bounds = new Rectangle[labels.length-1];
for(int i=0, j=0; i<labels.length; i++) {
if ( i!=index ) {
bounds[j]=getBounds(labels[i],fields[i]);
j++;
}
}
return bounds;
}
/*
* Calcule les bounds d'un couple label/field
*/
private Rectangle getBounds(JLabel label, JComponent field) {
return label.getBounds().union(field.getBounds());
}
@Override
public void mouseDragged(MouseEvent e) {
if (moved) {
// on simule le mouvement pour déterminer s'il peut y avoir superposition
Rectangle newBounds = prepareMove(e);
//s'il n'y a pas superposition on déplacer
if ( !overlays(newBounds) ) {
doMove(newBounds);
}
else {
// sinon on mémorise qu'on a eu superposition
overlayed=true;
}
}
}
/**
* Simule le mouvement en le stockant dans un Rectangle
*/
private Rectangle prepareMove(MouseEvent e) {
Rectangle bounds = getBounds(label, field);
bounds.setLocation(label.getX() + e.getX() - dx, label.getY() + e.getY() - dy);
return bounds;
}
/*
* Teste si le rectangle passé en argument se superpose à l'un des rectangles mémorisés dans bounds[]
*/
private boolean overlays(Rectangle movedBounds) {
for(Rectangle rbound : bounds) {
if ( rbound.intersects(movedBounds) ) {
return true;
}
}
return false;
}
/*
* Applique le mouvement stocké dans le tableau
*/
private void doMove(Rectangle newBounds) {
// on déplace
// la nouvelle position est l'ancienne plus la différence entre la position actuelle de la souris et la position relative de la souris au démarrage du déplacement
setLocation(newBounds.x, newBounds.y);
}
/*
* Mets un couple label/field en position passée en argument
*/
private void setLocation(int x, int y) {
label.setLocation(x, y);
field.setLocation(label.getX()+label.getWidth(), label.getY());
}
@Override
public void mouseReleased(MouseEvent e) {
if ( e.getButton()==MouseEvent.BUTTON1 && moved) {
stopMove();
}
}
private void stopMove() {
moved=false;
if ( overlayed ) {
// remet le couple label/field à la position mémorisée au démarrage si on a eu superposition
setLocation(startLocationX, startLocationY);
overlayed=false;
}
}
}
} |
Partager