En bref, je veux mettre le texte d'une JLabel
être celle d'un JTextField
dans un JPanel
(pnlUser
), puis faites glisser le JLabel
sur l'écran de JPanel
sur un autre JTextField
dans un autre JPanel
(pnlGrid
).Comment faire glisser un JLabel d'un JPanel dans un JFrame sur un JTextField dans un autre JPanel dans le même JFrame?
Voici les détails.
J'ai écrit un programme "Solitaire Scrabble". L'utilisateur peut placer le curseur de texte dans une cellule (JTextField
dans pnlGrid
) et taper une lettre qui est dans la liste des "User letters" (un JTextField
dans pnlUser
) OU l'utilisateur peut simuler en faisant glisser une lettre de " Lettres d'utilisateur "et le déposer dans la cellule de la grille de destination au pnlGrid
.
Je dis "simuler" parce que la lettre sélectionnée n'est pas réellement déplacée sur l'écran. J'utilise le pointeur de la souris HAND_CURSOR
pour rendre le glisser/déposer aussi réel que possible, mais je n'ai pas compris comment faire le HAND_CURSOR
"saisir" la lettre et faire glisser physiquement la lettre à travers le tableau à sa destination. En l'état, la lettre est mise en surbrillance mais laissée dans la zone "Lettres utilisateur" tandis que HAND_CURSOR
se déplace le long de la grille pendant l'opération de glissement. Quand il arrive à la cellule de destination dans pnlGrid
et que le bouton de la souris est relâché, la lettre est effacée de "User letters" et apparaît soudainement dans la cellule de la grille. Ainsi, la lettre est plus ou moins "téléportée" ("beam-up", Scotty) de "User letters" à une cellule de la grille. C'est trop abstrait. Je veux que la lettre de l'utilisateur soit à l'extrémité du doigt pointé de HAND_CURSOR et soit traînée le long de la grille dans la cellule de la grille où elle sera déposée, comme montré dans les 3 images ci-dessous.
Je l'ai fait avec succès arriver dans un petit programme de test (source ci-dessous) à l'aide JLayeredPane, mais je ne peux pas y arriver dans le jeu. Mais je ne savais rien de JLayeredPane jusqu'à il y a deux jours, donc je ne sais pas vraiment ce que je fais. (J'ai adapté un programme de tutoriel Oracle qui démultiplie JLayeredPane.)
Je viens de lire à propos du "volet de verre" et j'ai pensé qu'il serait peut-être plus facile à implémenter jusqu'à ce que je télécharge la source de cette démo, qui est assez longue, donc depuis c'est totalement nouveau et sera encore plus difficile à adapter.
Je pensais avant que je passe plus d'heures dans la frustration que je devrais demander:
Est-ce un JLayeredPane
ou une approche setGlassPane
appropriée? Y at-il un moyen plus facile ou mieux de faire glisser un JLabel
d'un JPanel
sur un autre JPanel
?
(L'approche du programme est de déterminer quel « lettre utilisateur » est pointé du, stocker cette lettre dans un JLabel
, et assurez-vous que pendant mouseDragged
le bout du doigt HAND_CURSOR
est juste au centre bas de la lettre.)
package mousemoveletter;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import static java.awt.Color.*;
import java.awt.event.*;
import static javax.swing.SwingUtilities.invokeLater;
public class LayeredPaneDemo extends JPanel
{
private static final int USER7 = 7;
static Cursor HAND = new Cursor(Cursor.HAND_CURSOR);
static Cursor ARROW = new Cursor(Cursor.DEFAULT_CURSOR);
private static JLayeredPane layeredPane;
private static JLabel lblToMove;
private static JPanel pnlUser;
private static JPanel pnlGrid;
private static final JTextField[] txtUser = new JTextField[USER7];
public LayeredPaneDemo() // constructor
{
pnlGrid = new JPanel();
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(240, 240));
pnlGrid.setSize(140, 140);
pnlGrid.setBorder(new EtchedBorder(RED, GREEN));
pnlGrid.setBackground(YELLOW);
lblToMove = new JLabel("XXX");
lblToMove.setSize(new Dimension(40,40));
layeredPane.add(pnlGrid, 0,0);
layeredPane.add(lblToMove, new Integer(0), -1);
add(layeredPane);
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("LayeredPaneDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new LayeredPaneDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
makeUser();
frame.add(pnlUser);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
invokeLater(new Runnable()
{
public void run() {
createAndShowGUI();
}
});
}
private static void makeUser(){
pnlUser = new JPanel(new GridLayout(1,USER7));
pnlUser.setPreferredSize(new Dimension(225, 50));
pnlUser.setBackground(Color.green);
pnlUser.setBorder(BorderFactory.createLineBorder(Color.BLUE));
for(int k = 0; k < USER7; k++)
{
txtUser[k] = new JTextField("" + (char)(Math.random()*26+65));
txtUser[k].setName("" + k);
txtUser[k].setEditable(false);
txtUser[k].addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseDragged(MouseEvent e)
{
lblToMove.setCursor(HAND);
int w = Integer.parseInt(e.getComponent().getName());
lblToMove.setText(txtUser[w].getText());
layeredPane.setLayer(lblToMove, 0, 0);
lblToMove.setLocation(e.getX() + (e.getComponent().getWidth())*w,
e.getY() + layeredPane.getHeight() - e.getComponent().getHeight()/2);
};
});
txtUser[k].addMouseListener(new MouseAdapter()
{
public void mouseReleased(MouseEvent e)
{
lblToMove.setCursor(ARROW);
}
});
pnlUser.add(txtUser[k]);
}
}
}
Try this [exemple] (http://stackoverflow.com/a/2562685/230513) et [variation] (http://stackoverflow.com/a/2563350/230513) – trashgod
@ trashgod-- MERCI pour l'exemple et la variation. Après BEAUCOUP d'heures de quasi-échecs à essayer d'adapter votre idée à ma situation, j'ai ENFIN ce que je pense qui va fonctionner pour moi. Comme il est 5 heures mardi, je pense que j'attendrai jeudi pour essayer de l'implémenter dans le jeu actuel! – DSlomer64