¿Agregar un JLabel a un JPanel “esconde” el JPanel?

Si tengo unos pocos JPanels en un GridLayout, cada uno con un MouseAdapter, y luego creo JLabels (con texto) y los agrego a cada uno de los JPanels. Tenga en cuenta que los JLabels no tienen oyentes. Si renderizo esto e bash hacer clic en un JPanel, o, finalmente, trato de hacer clic en JLabel, ¿MouseAdapter lo registrará como un evento?

Básicamente, quiero que los JPanels registren eventos y los JPanels solo para mostrar el texto en la parte superior de los JPanels. Además, los paneles tienen color de fondo.

Si JLabel “oculta” los eventos de registro, ¿cómo puedo solucionar esto?

El componente superior recibirá el clic del mouse. Cuánto cubrirá JLabel dependerá de su tamaño y del administrador de diseño de JPanel. Una forma es darle al oyente el JLabel (como también se ha mencionado anteriormente), pero otra forma de hacerlo es como lo describo a continuación, y aunque quizás no sea la mejor, funcionó bien para mí:

1) Un JLayeredPane contiene todo y tiene un MouseAdapter que se agrega como MouseListener y MouseMotionListener.

2) Un JPanel, llamado “placa”, que usa GridLayout (8, 8) y tiene el tamaño exacto cuando el JLayeredPane se agrega a la capa inferior del panel en capas, o para ser precisos, el JLayeredPane.DEFAULT_LAYER.

3) Este JPanel contiene 64 otros cuadrados JPanel pequeños en el GridLayout (en realidad los cuadrados se extienden desde JPanel), y cada uno usa GridBagLayout.

4) Las piezas de ajedrez son JLabels y están en los cuadrados de JPanel.

5) En el método MouseAdapter mousePressed, obtengo el punto, p, en el que se encuentra el mouse en via e.getPoint (si e es el objeto MouseEvent pasado al método). Luego descubro qué casilla contiene este punto llamando a findComponentAt (p) en la placa JPanel. Luego verifico si este cuadrado contiene una pieza. Si es así, la pieza se elimina del cuadrado y se agrega directamente al JLayeredPane.DRAG_LAYER de JLayeredPane.

6) Si una pieza de ajedrez se mantiene en el JLayeredPane.DRAG_LAYER del JLayeredPane, el método MouseDragged de MouseAdapter controlará la ubicación de la pieza.

7) En mouseRelease, descubro nuevamente qué cuadrado contiene la ubicación o el punto del mouse con la misma técnica que la anterior, usando findComponentAt (p) y si es un cuadrado válido, elimino la pieza de ajedrez del JLayeredPane.DRAG_LAYER de JLayeredPane y coloco en el cuadrado Si está fuera del tablero o no es un cuadrado válido, devuelvo la pieza de ajedrez a la ubicación original.

Tenga en cuenta que si la placa JPanel no llena por completo el JLayeredPane, entonces su desplazamiento dentro del JLayeredPane se debe utilizar para corregir la ubicación Point, p antes de llamar a findComponentAt (p) ya que MouseAdapter devolverá Points relativos al JLayeredPane y no a la placa JPanel .

Por ejemplo:

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; } } 

Los JLabels sin oyentes de ratón no consumirán eventos de mouse, sino que se pasarán al JPanel. Aquí hay un ejemplo:

 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); } }