是否将JLabel添加到JPanel“隐藏”JPanel?

如果我在GridLayout中有几个JPanel,每个都有一个MouseAdapter,然后创buildJLabel(带有文本)并添加到每个JPanel。 注意JLabels没有监听器。 如果我渲染这个并尝试点击一个JPanel,或者最终尝试点击JLabel,那么MouseAdapter会将这个注册为一个事件?

基本上我想JPanels注册事件和JPanels只显示文本顶部的JPanels。 此外,面板具有背景颜色。

如果JLabel“隐藏”注册事件,我该如何解决这个问题?

顶部组件将获得鼠标点击。 JLabel将覆盖多less将取决于其大小和JPanel的布局pipe理器。 一种方法是给JLabel的听众(正如上面已经提到的那样),但是另一种方法是如下所述,虽然也许不是最好的方式,但它对我来说很好:

1)一个JLayeredPane容纳所有东西,并且有一个MouseAdapter被添加为MouseListener和MouseMotionListener。

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,如果是有效方形,则从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 = px - PIECE_WIDTH/2; int y = py - PIECE_WIDTH/2; piece.setLocation(x, y); delta = new Point(px - x, py - 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 = px - delta.x; int y = py - 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; } } 

没有鼠标监听器的JLabel不会消耗鼠标事件 – 它们被传递给JPanel。 这里是一个例子:

 public class LabelOnPanel { public static void main(String[] args) { final JPanel mainPanel = new JPanel(new BorderLayout()); mainPanel.add(new JLabel("This is a JLabel covering the entire panel")); mainPanel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { JOptionPane.showMessageDialog(mainPanel, "Panel received click"); } }); JFrame frame = new JFrame(); frame.setBounds(100, 100, 300, 300); frame.add(mainPanel, BorderLayout.CENTER); frame.setVisible(true); } }