2011-01-14 3 views
0

Si j'ai quelques JPanels dans un GridLayout, chacun avec un MouseAdapter, puis créer des JLabels (avec du texte) et les ajouter à chacun des JPanels. Notez que les JLabels n'ont pas d'écouteurs. Si je rends cela et que j'essaie de cliquer sur un JPanel, ou, en fin de compte, que je clique sur le JLabel, le MouseAdapter l'enregistrera-t-il comme un événement?Est-ce que l'ajout d'un JLabel à un JPanel "cache" le JPanel?

Fondamentalement, je veux que les JPanels enregistrent des événements et que les JPanels affichent juste le texte au-dessus des JPanels. De plus, les panneaux ont une couleur de fond.

Si le JLabel "cache" les événements de l'enregistrement, comment puis-je contourner cela?

+0

Pourquoi ne pas vous inscrire auditeurs avec les JLabels? Peut-être que si vous pouviez nous fournir le rationnel pour cette conception, nous pouvons suggérer quelques approches ... –

+0

Eh bien c'est un jeu d'échecs, des carrés composés de JPanels, des morceaux composés de texte sur le dessus. Et tu as raison. J'ai changé l'adaptateur pour les JLabels. Mais se demandant, les JLabels ajoutés aux JPanels occupent-ils autant d'espace que les JPanels eux-mêmes? Je veux dire, est-ce que l'utilisateur doit cliquer sur le texte dans le carré ou peut-il toujours cliquer n'importe où dans le carré et le JLable détectera l'événement? –

Répondre

9

Le composant supérieur obtiendra le clic de la souris. La couverture de JLabel dépendra de sa taille et du gestionnaire de disposition de JPanel. Une façon est de donner l'écouteur au JLabel (comme cela a été mentionné plus haut), mais comme je le décris ci-dessous, et bien que ce ne soit pas la meilleure, ça a bien marché pour moi:

1 Un JLayeredPane contient tout et a un MouseAdapter qui est ajouté en tant que MouseListener et MouseMotionListener. 2) Un JPanel, appelé "tableau", qui utilise GridLayout (8, 8) et qui a la même taille que le JLayeredPane est ajouté à la couche inférieure du volet en couches, ou pour être précis, le JLayeredPane.DEFAULT_LAYER.

3) Ce JPanel contient 64 autres petits carrés JPanel dans le GridLayout (en fait les carrés s'étendent de JPanel), et chacun utilise GridBagLayout.

4) Les pièces d'échecs sont des JLabels et sont maintenues par les carrés JPanel.

5) Dans la méthode MouseAdapter mousePressed, j'obtiens le point, p, que la souris se trouve à via e.getPoint (si e est l'objet MouseEvent passé à la méthode). Je découvre alors quel carré contient ce point en appelant findComponentAt (p) sur le tableau JPanel. Je vérifie ensuite si ce carré contient une pièce. Si c'est le cas, la pièce est retirée du carré et ajoutée directement au JLayeredPane JLayeredPane.DRAG_LAYER.

6) Si une pièce d'échec est conservée dans le JLayeredPane JLayeredPane.DRAG_LAYER, la méthode mouseDragged de MouseAdapter contrôlera l'emplacement de la pièce.

7) Sur mouseRelease, je trouve de nouveau quel carré contient l'emplacement de la souris ou Point par la même technique que ci-dessus, en utilisant findComponentAt (p) et si c'est un carré valide, je retire le morceau du JLayeredPane de JLayeredPane .DRAG_LAYER et placez-le dans le carré. Si c'est hors du tableau ou pas un carré valide, je renvoie la pièce d'échecs à l'emplacement d'origine. Notez que si la carte JPanel ne remplit pas complètement le JLayeredPane, alors son offset dans le JLayeredPane doit être utilisé pour corriger l'emplacement Point, p avant d'appeler findComponentAt (p) puisque le MouseAdapter retournera des Points par rapport au JLayeredPane pas le conseil JPanel.

Par exemple:

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

} 
+0

... et mate! (désolé, n'a pas pu résister, le sujet étant des échecs et tout). –

+0

Haha bon: P Je déteste MouseListeners ... pourquoi ont-ils à rendre la vie misérable avec NullPointerExceptions, pourquoi. Oh et merci Hovercraft au fait, ça semble bien ... mais ça pourrait être difficile d'essayer de l'adapter à mon codage .. –

+0

Wow, Est-ce que je peux faire un truc si merveilleux un jour? Je suis perplexe, LOL, trop bon, cette peinture thingy rocks :-) –

0

JLabels sans écouteurs de souris ne consommera pas les événements de souris - ils sont passés à la JPanel. Voici un exemple:

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