頂部組件將獲得鼠標點擊。 JLabel將覆蓋多少將取決於其大小以及JPanel的佈局管理器。一種方法是給聽衆JLabel(如上所述),但是另一種方式如下所述,儘管可能不是最好的方式,但它對我來說很好:
1 )JLayeredPane可容納所有內容,並具有一個作爲MouseListener和MouseMotionListener添加的MouseAdapter。
2)一個名爲「board」的JPanel,它使用GridLayout(8,8),並且與JLayeredPane添加到分層窗格的底層或準確地說,是JLayeredPane.DEFAULT_LAYER的確切大小。 3)這個JPanel在GridLayout中保存了64個其他的小JPanel正方形(實際上從JPanel延伸的正方形),並且每個都使用GridBagLayout。
4)棋子是JLabels,由JPanel正方形。
5)在MouseAdapter mousePressed方法中,我通過e.getPoint(如果e是傳遞給方法的MouseEvent對象)獲取鼠標位於的Point,p。然後我通過調用板JPanel上的findComponentAt(p)來找出哪個方塊保持了這一點。然後我檢查一下這個廣場是否有一塊。如果是這樣的話,該部分將從方塊中移除並直接添加到JLayeredPane的JLayeredPane.DRAG_LAYER中。 6)如果JLayeredPane的JLayeredPane.DRAG_LAYER中有棋子,MouseAdapter的mouseDragged方法將控制棋子的位置。
7)在mouseRelease上,我再次使用findComponentAt(p)找出哪個方形包含鼠標的位置或Point,使用findComponentAt(p),如果它是有效方形,則從JLayeredPane的JLayeredPane中移除棋子.DRAG_LAYER並放置在廣場上。如果它不在棋盤上或不是有效的方格,我將棋子歸還原來的位置。
請注意,如果主板JPanel沒有完全填充JLayeredPane,則在調用findComponentAt(p)之前必須使用JLayeredPane內的偏移量來更正位置Point,p,因爲MouseAdapter將返回相對於JLayeredPane的點不是董事會JPanel。
例如:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Chess2 {
private static void createAndShowUI() {
JFrame frame = new JFrame("Chess 2");
frame.getContentPane().add(new Chess2Gui().getMainComponent());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class Chess2Gui {
private static final int RANKS = 8;
private static final int FILES = 8;
private static final Color DARK_COLOR = new Color(0, 100, 0);
private static final Color LIGHT_COLOR = new Color(200, 200, 200);
private static final Color DARK_PIECE_COLOR = Color.black;
private static final int SQR_WIDTH = 80;
private static final int PIECE_WIDTH = 60;
private static final Dimension SQR_SIZE = new Dimension(SQR_WIDTH, SQR_WIDTH);
private JLayeredPane mainLayeredPane = new JLayeredPane();
private JPanel board = new JPanel(new GridLayout(RANKS, FILES));
private JPanelSquare[][] jPanelSquareGrid = new JPanelSquare[RANKS][FILES];
public Chess2Gui() {
for (int rank = 0; rank < RANKS; rank++) {
for (int file = 0; file < FILES; file++) {
Color bkgd = DARK_COLOR;
if (rank % 2 == file % 2) {
bkgd = LIGHT_COLOR;
}
jPanelSquareGrid[rank][file] = new JPanelSquare(rank, file, bkgd);
jPanelSquareGrid[rank][file].setPreferredSize(SQR_SIZE);
board.add(jPanelSquareGrid[rank][file]);
}
}
board.setSize(board.getPreferredSize());
board.setLocation(0, 0);
mainLayeredPane.add(board, JLayeredPane.DEFAULT_LAYER);
mainLayeredPane.setPreferredSize(board.getPreferredSize());
ImageIcon icon = new ImageIcon(ImageUtils2.createImage(PIECE_WIDTH, DARK_PIECE_COLOR));
JLabel chessPiece = new JLabel(icon, SwingConstants.CENTER);
jPanelSquareGrid[1][3].add(chessPiece);
MyMouseAdapter mouseAdapter = new MyMouseAdapter();
mainLayeredPane.addMouseListener(mouseAdapter);
mainLayeredPane.addMouseMotionListener(mouseAdapter);
}
public JComponent getMainComponent() {
return mainLayeredPane;
}
private class MyMouseAdapter extends MouseAdapter {
private JLabel piece = null;
private Point delta = null;
private int oldRank = -1;
private int oldFile = -1;
@Override
public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
Component c = board.getComponentAt(p);
for (int rank = 0; rank < jPanelSquareGrid.length; rank++) {
for (int file = 0; file < jPanelSquareGrid[rank].length; file++) {
if (jPanelSquareGrid[rank][file] == c) {
if (jPanelSquareGrid[rank][file].getChessPiece() != null) {
// the jPanelSquares are derived from JPanel but have a
// few of their own methods
piece = jPanelSquareGrid[rank][file].getChessPiece();
jPanelSquareGrid[rank][file].remove(piece);
oldRank = rank;
oldFile = file;
mainLayeredPane.add(piece, JLayeredPane.DRAG_LAYER);
int x = p.x - PIECE_WIDTH/2;
int y = p.y - PIECE_WIDTH/2;
piece.setLocation(x, y);
delta = new Point(p.x - x, p.y - y);
board.revalidate();
mainLayeredPane.repaint();
return;
}
}
}
}
oldFile = -1;
oldRank = -1;
}
@Override
public void mouseDragged(MouseEvent e) {
if (piece != null) {
Point p = e.getPoint();
int x = p.x - delta.x;
int y = p.y - delta.y;
piece.setLocation(x, y);
mainLayeredPane.revalidate();
mainLayeredPane.repaint();
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (piece != null) {
JPanelSquare sqr = (JPanelSquare) board.getComponentAt(e.getPoint());
mainLayeredPane.remove(piece);
if (sqr == null || !validMove(sqr)) {
jPanelSquareGrid[oldRank][oldFile].add(piece);
} else {
sqr.add(piece);
}
piece = null;
delta = null;
oldRank = -1;
oldFile = -1;
board.revalidate();
mainLayeredPane.repaint();
}
}
// just a pawn's moves
private boolean validMove(JPanelSquare sqr) {
int rank = sqr.getRank();
int file = sqr.getFile();
if (file != oldFile) {
return false;
}
if (oldRank == 1 && (rank != 2 && rank != 3)) {
return false;
}
if (oldRank != 1 && rank != oldRank + 1) {
return false;
}
return true;
}
}
}
@SuppressWarnings("serial")
class JPanelSquare extends JPanel {
private int rank;
private int file;
private JLabel chessPiece = null;
public JPanelSquare(int rank, int file, Color bkgrnd) {
this.rank = rank;
this.file = file;
setBackground(bkgrnd);
setLayout(new GridBagLayout());
}
public int getRank() {
return rank;
}
public int getFile() {
return file;
}
@Override
public Component add(Component c) {
chessPiece = (JLabel)c;
return super.add(c);
}
@Override
public void remove(Component comp) {
chessPiece = null;
super.remove(comp);
}
public JLabel getChessPiece() {
return chessPiece;
}
}
class ImageUtils2 {
public static BufferedImage createImage(int size, Color color) {
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setColor(color);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.fillOval(size/3, 0, size/3, size/3);
g2.fillOval(size/4, size/4, size/2, 2*size/3);
g2.fillOval(size/6, 2*size/3, 2*size/3, size/2);
g2.dispose();
return img;
}
}
你爲什麼不用JLabels註冊監聽器?也許如果你能爲我們提供這種設計的理性,我們可以提出一些方法...... – 2011-01-14 03:12:56
這是一款國際象棋遊戲,由JPanels組成的正方形,由頂部文字組成的棋子。你說得對。我將適配器更改爲JLabels。但是奇怪的是,JLabels添加到JPanels中佔用了JPanels自己的太多空間嗎?我的意思是,用戶必須點擊廣場中的文字,還是可以點擊廣場中的任何地方,JLable會檢測到該事件? – 2011-01-14 03:34:32