2011-01-14 66 views
0

如果我在GridLayout中有幾個JPanel,每個都有一個MouseAdapter,然後創建JLabels(帶有文本)並添加到每個JPanel。請注意JLabels沒有監聽器。 如果我渲染並嘗試單擊一個JPanel,或者最終嘗試單擊JLabel,那麼MouseAdapter是否將該事件註冊爲事件?是否將JLabel添加到JPanel中「隱藏」JPanel?

基本上我希望JPanels註冊事件,JPanels只顯示JPanel頂部的文本。此外,面板具有背景色。

如果JLabel確實「隱藏」註冊事件,我該如何解決這個問題?

+0

你爲什麼不用JLabels註冊監聽器?也許如果你能爲我們提供這種設計的理性,我們可以提出一些方法...... – 2011-01-14 03:12:56

+0

這是一款國際象棋遊戲,由JPanels組成的正方形,由頂部文字組成的棋子。你說得對。我將適配器更改爲JLabels。但是奇怪的是,JLabels添加到JPanels中佔用了JPanels自己的太多空間嗎?我的意思是,用戶必須點擊廣場中的文字,還是可以點擊廣場中的任何地方,JLable會檢測到該事件? – 2011-01-14 03:34:32

回答

9

頂部組件將獲得鼠標點擊。 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; 
    } 

} 
0

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