2017-01-07 1 views
1

스윙을 사용하여 체커 게임을 만들려고하고 있는데 이미 보드를 설정했습니다 (here).다른 JPanel 위에 정확한 JPanel 미러를 만드는 방법

각 개별 타일은 GridBagLayout 관리자를 통해 구성된 JPanel의 GUI에 배치됩니다. 개별 검사기 조각을 타일 위에 놓기 위해 보드 타일을 보유하고있는 JPanel의 정확한 복사본 인 다른 JPanel을 만들고 싶습니다. 사본 JPanel은 체커 조각을 들고 투명하게되어 체커 조각이 게임 보드 위에 놓 이도록합니다.

두 번째 JPanel을 어떻게 만들 수 있습니까? 그리고 가능하지 않다면, 바둑판에 체커 조각을 만드는 더 좋은 대안은 무엇입니까?

+0

가'내가 또 다른 인 JPanel을 만들려면 보드 타일을 가지고있는 JPanel의 정확한 복사본입니다. "- 왜 이것을하고 싶지 않은지. 다른 접근 방법은 http://stackoverflow.com/questions/2561690/placing-component-on-glass-pane/2562685#2562685를 확인하십시오. – camickr

+0

* "더 나은 대안"* JBuitton 구성 요소의'GridLayout'. 체스 보드를 기반으로하는 [예제] (http://stackoverflow.com/q/21142686/418556)입니다. –

답변

1

디자인을 개선하고 단순화 할 수 있습니다. 훨씬 간단한 방법은 GridLayout에 보유 된 JPanel 셀의 그리드를 만든 다음 JLabel 조각을 조각을 보유 할 개별 셀에 추가하는 것입니다. 미러링하거나 복제 할 필요가 없습니다. 그런 다음 사용자가 마우스 리스너 코드에서 조각을 클릭하고 드래그 할 수있게하려면 조각을 유리판으로 들어 올리거나 자체 JLayeredPane을 사용하여 이동하십시오.

예를 들어이 프로그램을 실행하여 정확히 무슨 뜻인지 확인해보십시오. 그것은 단지 한 조각을 가지고 있으며, 논리는 간단하다 - 단지 어두운 광장에 조각으로 낙하 할 수 있지만 개념을 보여 않습니다

enter image description here

import java.awt.BasicStroke; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.Graphics2D; 
import java.awt.GridBagLayout; 
import java.awt.GridLayout; 
import java.awt.Point; 
import java.awt.RenderingHints; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.image.BufferedImage; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class ChessEg extends JPanel { 
    private static final int IMG_W = 60; 
    private static final int CELL_WIDTH = 80; 
    private static final Color PIECE_COLOR = Color.RED.darker(); 
    private ChessBoardPanel chessBoardPanel = new ChessBoardPanel(CELL_WIDTH); 
    private JLabel pieceLabel = new JLabel(); 

    public ChessEg() { 
     ChessBrdPanelListener pieceListener = new ChessBrdPanelListener(); 
     chessBoardPanel.addMouseListener(pieceListener); 
     chessBoardPanel.addMouseMotionListener(pieceListener); 
     pieceLabel.setIcon(createPieceIcon()); 
     setLayout(new BorderLayout()); 
     add(chessBoardPanel, BorderLayout.CENTER); 
     chessBoardPanel.getCellAt(1, 0).add(pieceLabel); 
    } 

    private Icon createPieceIcon() { 
     BufferedImage img = new BufferedImage(IMG_W, IMG_W, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = img.createGraphics(); 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setColor(PIECE_COLOR); 
     g2.fillOval(2, 2, IMG_W - 4, IMG_W - 4); 
     g2.setStroke(new BasicStroke(2f)); 
     g2.setColor(Color.DARK_GRAY); 
     g2.drawOval(2, 2, IMG_W - 4, IMG_W - 4); 
     g2.dispose(); 
     return new ImageIcon(img); 
    } 

    public boolean isNewChessCellValid(ChessCell newChessCell) { 
     // right now, just checks if placing on a dark square 
     // TODO: improve logic 
     return ChessBoardPanel.DARK_COLOR.equals(newChessCell.getBackground()); 
    } 

    private class ChessBrdPanelListener extends MouseAdapter { 
     private JLabel label; 
     private ChessCell originalChessCell; 
     private JPanel glassPane; 
     private Point gpP; 
     private ChessCell newChessCell; 

     @Override 
     public void mousePressed(MouseEvent e) { 
      if (e.getButton() != MouseEvent.BUTTON1) { 
       return; 
      } 
      JPanel src = (JPanel) e.getSource(); 
      Component comp = src.getComponentAt(e.getPoint()); 
      if (comp != null && ((JComponent) comp).getComponentCount() == 1) { 
       originalChessCell = (ChessCell) comp; 
       label = (JLabel) originalChessCell.getComponent(0); 
      } else { 
       return; 
      } 
      originalChessCell.remove(label); 
      originalChessCell.revalidate(); 
      originalChessCell.repaint(); 
      glassPane = (JPanel) SwingUtilities.getRootPane(originalChessCell).getGlassPane(); 
      glassPane.setVisible(true); 
      gpP = glassPane.getLocationOnScreen(); 
      glassPane.setLayout(null); 
      int x = e.getXOnScreen() - gpP.x - label.getWidth()/2; 
      int y = e.getYOnScreen() - gpP.y - label.getHeight()/2; 
      label.setLocation(x, y); 
      label.setSize(label.getPreferredSize()); 
      glassPane.add(label); 
      glassPane.repaint(); 
      e.consume(); 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
      if (label == null) { 
       return; 
      } 
      int x = e.getXOnScreen() - gpP.x - label.getWidth()/2; 
      int y = e.getYOnScreen() - gpP.y - label.getHeight()/2; 
      label.setLocation(x, y); 
      repaint(); 
      JPanel src = (JPanel) e.getSource(); 
      Component comp = src.getComponentAt(e.getPoint()); 
      if (comp != null) { 
       newChessCell = (ChessCell) comp; 
       if (isNewChessCellValid(newChessCell)) { 
        newChessCell.add(label); 
       } else { 
        originalChessCell.add(label); 
       } 
      } else { 
       originalChessCell.add(label); 
      } 


      label = null; 
      glassPane.setVisible(false); 
      revalidate(); 
      repaint(); 
     } 

     @Override 
     public void mouseDragged(MouseEvent e) { 
      if (label == null) { 
       return; 
      } 
      int x = e.getXOnScreen() - gpP.x - label.getWidth()/2; 
      int y = e.getYOnScreen() - gpP.y - label.getHeight()/2; 
      label.setLocation(x, y); 
      repaint(); 
     } 
    } 

    private static void createAndShowGui() { 
     ChessEg mainPanel = new ChessEg(); 
     JFrame frame = new JFrame("Chess Example"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 

@SuppressWarnings("serial") 
class ChessBoardPanel extends JPanel { 
    public static final Color DARK_COLOR = new Color(180, 85, 0); 
    public static final Color LIGHT_COLOR = new Color(220, 190, 160); 
    private int cellWidth; 
    private ChessCell[][] panelGrid = new ChessCell[8][8]; 

    public ChessBoardPanel(int cellWidth) { 
     this.cellWidth = cellWidth; 
     setLayout(new GridLayout(8, 8)); 
     for (int i = 0; i < panelGrid.length; i++) { 
      for (int j = 0; j < panelGrid[i].length; j++) { 
       char rank = (char) ('8' - i); 
       char file = (char) ('a' + j); 
       panelGrid[i][j] = new ChessCell(rank, file); 
       panelGrid[i][j].setPreferredSize(new Dimension(cellWidth, cellWidth)); 
       Color bg = i % 2 == j % 2 ? LIGHT_COLOR : DARK_COLOR; 
       panelGrid[i][j].setBackground(bg); 
       add(panelGrid[i][j]); 
      } 
     } 
    } 

    public JPanel getCellAt(int i, int j) { 
     return panelGrid[i][j]; 
    } 

    public int getCellWidth() { 
     return cellWidth; 
    } 
} 

@SuppressWarnings("serial") 
class ChessCell extends JPanel { 
    private char rank; 
    private char file; 

    public ChessCell(char rank, char file) { 
     super(new GridBagLayout()); 
     this.rank = rank; 
     this.file = file; 
    } 

    public char getRank() { 
     return rank; 
    } 

    public char getFile() { 
     return file; 
    } 

    @Override 
    public String toString() { 
     return "ChessCell [rank=" + rank + ", file=" + file + "]"; 
    } 
} 
+0

개별 게임 타일은 JLabel ImageIcon을 통해 생성됩니다. 어떻게 게임 조각 JLabel을 타일 JLabel에 겹치게합니까? – Smaugy

+0

@ GandalfDaGrey : 타일을 JLabel이 아닌 JPanel로 만들고 해당 이미지를 paintComponent 메소드에 표시합니다. 또는 JLabel에 GridBagLayout과 같은 적절한 레이아웃 관리자를 제공하십시오. 이 레이아웃을 사용하면 JLabel에 추가 된 단일 구성 요소가 자동으로 중앙에 배치됩니다. 그렇지 않으면 당신은 kludgy 수학과 함께 JLayeredPane을 사용하는 것에 대해 이야기하고 있습니다. –

+0

@ GandalfDaGrey : 위의 예를 참조하십시오. –