2011-01-12 41 views
3

我不知道爲什麼它不會顯示。首先,我創建組件的一個實例,然後將其添加到二維JPanel數組中的某個元素中。然後我遍歷該數組並將每個JPanel添加到另一個JPanel容器,該容器將容納所有JPanel。如何使我的自定義Swing組件可見?

然後我將最後一個容器添加到我的JFrame窗口並將可見性設置爲true,它應該可見?

public class View extends JFrame { 

    Board  gameBoard; 
    JFrame  gameWindow = new JFrame("Chess"); 
    JPanel  gamePanel = new JPanel(); 
    JPanel[][] squarePanel = new JPanel[8][8]; 
    JMenuBar gameMenu  = new JMenuBar(); 
    JButton restartGame = new JButton("Restart"); 
    JButton pauseGame = new JButton("Pause"); 
    JButton log   = new JButton("Log"); 

    View(Board board){ 
     gameWindow.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     gameWindow.setSize(400, 420); 
     gameWindow.getContentPane().add(gamePanel, BorderLayout.CENTER); 
     gameWindow.getContentPane().add(gameMenu, BorderLayout.NORTH); 
     gameMenu.add(restartGame); 
     gameMenu.add(pauseGame); 
     gameMenu.add(log); 
     gameBoard = board; 
     drawBoard(gameBoard); 
     gameWindow.setResizable(false); 
     gameWindow.setVisible(true); 

    } 

    public void drawBoard(Board board){ 
     for(int row = 0; row < 8; row++){ 
      for(int col = 0; col < 8; col++){ 
       Box box = new Box(board.getSquare(col, row).getColour(), col, row); 
       squarePanel[col][row] = new JPanel(); 
       squarePanel[col][row].add(box); 
      } 
     } 
     for(JPanel[] col : squarePanel){ 
      for(JPanel square : col){ 
       gamePanel.add(square); 
      } 
     } 
    } 
} 

@SuppressWarnings("serial") 
class Box extends JComponent{ 
    Color boxColour; 
    int col, row; 
    public Box(Color boxColour, int col, int row){ 
     this.boxColour = boxColour; 
     this.col = col; 
     this.row = row; 
     repaint(); 
    } 
    protected void paintComponent(Graphics drawBox){ 
     drawBox.setColor(boxColour); 
     drawBox.drawRect(50*col, 50*row, 50, 50); 
     drawBox.fillRect(50*col, 50*row, 50, 50); 
    } 
} 

最後一個問題。注意每個Box組件都有一個位置,當將組件添加到JPanel並將JPanel添加到我的JFrame時,位置會發生什麼變化? 它與其他Box組件有相同的位置嗎?

+0

哪裏是你的`main`?據我所知,View的構造函數從來沒有被調用過。另外,View類是一個`JFrame`,它永遠不可見。 – 2011-01-12 21:37:10

+0

對,忘記告訴你。構造函數在另一個類Game中調用,其中「board」作爲參數傳遞。 董事會持有一個Square [] []和getSquare方法得到的索引列,行的平方。 getColour方法從square獲取squareColour屬性。該板通過循環遍歷數組來設置構造函數中的squareColour。 – 2011-01-12 21:41:17

+0

gameWindow變得可見? 另外,奇怪的是我的菜單是可見的,按鈕也是。 這只是沒有的盒子。 – 2011-01-12 21:45:13

回答

5

我試着擴展JPanel,取而代之的是在我的菜單下有一個小的10x10像素灰色框。最開始

當您使用JComponent時,首選大小爲(0,0),這就是您什麼都看不到的原因。

當您使用JPanel時默認使用FlowLayout,FlowLayout在每個組件添加到面板之前/之後都有一個5像素的間隙。由於您不添加任何組件,因此您可以獲得大小(10,10)的優先大小。

因此,當您進行自定義繪畫時,您需要重寫getPreferredSize()方法以返回您打算實現的自定義繪畫的適當值。

編輯:

import java.awt.*; 
import java.awt.event.*; 
import java.util.*; 
import javax.swing.*; 

public class ChessBoard extends JFrame implements MouseListener, MouseMotionListener 
{ 
    JLayeredPane layeredPane; 
    JPanel chessBoard; 
    JLabel chessPiece; 
    int xAdjustment; 
    int yAdjustment; 

    public ChessBoard() 
    { 
     Dimension boardSize = new Dimension(600, 600); 

     // Use a Layered Pane for this this application 

     layeredPane = new JLayeredPane(); 
     layeredPane.setPreferredSize(boardSize); 
     layeredPane.addMouseListener(this); 
     layeredPane.addMouseMotionListener(this); 
     getContentPane().add(layeredPane); 

     // Add a chess board to the Layered Pane 

     chessBoard = new JPanel(); 
     chessBoard.setLayout(new GridLayout(8, 8)); 
     chessBoard.setPreferredSize(boardSize); 
     chessBoard.setBounds(0, 0, boardSize.width, boardSize.height); 
     layeredPane.add(chessBoard, JLayeredPane.DEFAULT_LAYER); 

     // Build the Chess Board squares 

     for (int i = 0; i < 8; i++) 
     { 
      for (int j = 0; j < 8; j++) 
      { 
       JPanel square = new JPanel(new BorderLayout()); 
       square.setBackground((i + j) % 2 == 0 ? Color.red : Color.white); 
       chessBoard.add(square); 
      } 
     } 

     // Add a few pieces to the board 

     ImageIcon duke = new ImageIcon("dukewavered.gif"); // add an image here 

     JLabel piece = new JLabel(duke); 
     JPanel panel = (JPanel)chessBoard.getComponent(0); 
     panel.add(piece); 
     piece = new JLabel(duke); 
     panel = (JPanel)chessBoard.getComponent(15); 
     panel.add(piece); 
    } 

    /* 
    ** Add the selected chess piece to the dragging layer so it can be moved 
    */ 
    public void mousePressed(MouseEvent e) 
    { 
     chessPiece = null; 
     Component c = chessBoard.findComponentAt(e.getX(), e.getY()); 

     if (c instanceof JPanel) return; 

     Point parentLocation = c.getParent().getLocation(); 
     xAdjustment = parentLocation.x - e.getX(); 
     yAdjustment = parentLocation.y - e.getY(); 
     chessPiece = (JLabel)c; 
     chessPiece.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment); 

     layeredPane.add(chessPiece, JLayeredPane.DRAG_LAYER); 
     layeredPane.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); 
    } 

    /* 
    ** Move the chess piece around 
    */ 
    public void mouseDragged(MouseEvent me) 
    { 
     if (chessPiece == null) return; 

     // The drag location should be within the bounds of the chess board 

     int x = me.getX() + xAdjustment; 
     int xMax = layeredPane.getWidth() - chessPiece.getWidth(); 
     x = Math.min(x, xMax); 
     x = Math.max(x, 0); 

     int y = me.getY() + yAdjustment; 
     int yMax = layeredPane.getHeight() - chessPiece.getHeight(); 
     y = Math.min(y, yMax); 
     y = Math.max(y, 0); 

     chessPiece.setLocation(x, y); 
    } 

    /* 
    ** Drop the chess piece back onto the chess board 
    */ 
    public void mouseReleased(MouseEvent e) 
    { 
     layeredPane.setCursor(null); 

     if (chessPiece == null) return; 

     // Make sure the chess piece is no longer painted on the layered pane 

     chessPiece.setVisible(false); 
     layeredPane.remove(chessPiece); 
     chessPiece.setVisible(true); 

     // The drop location should be within the bounds of the chess board 

     int xMax = layeredPane.getWidth() - chessPiece.getWidth(); 
     int x = Math.min(e.getX(), xMax); 
     x = Math.max(x, 0); 

     int yMax = layeredPane.getHeight() - chessPiece.getHeight(); 
     int y = Math.min(e.getY(), yMax); 
     y = Math.max(y, 0); 

     Component c = chessBoard.findComponentAt(x, y); 

     if (c instanceof JLabel) 
     { 
      Container parent = c.getParent(); 
      parent.remove(0); 
      parent.add(chessPiece); 
      parent.validate(); 
     } 
     else 
     { 
      Container parent = (Container)c; 
      parent.add(chessPiece); 
      parent.validate(); 
     } 
    } 

    public void mouseClicked(MouseEvent e) {} 
    public void mouseMoved(MouseEvent e) {} 
    public void mouseEntered(MouseEvent e) {} 
    public void mouseExited(MouseEvent e) {} 

    public static void main(String[] args) 
    { 
     JFrame frame = new ChessBoard(); 
     frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
     frame.setResizable(false); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 
} 
1

過去,我通過擴展JPanel而不是JComponent來解決這個問題。我找到了一個很好的例子here。下面是它的一個調整,這將畫一個框:

public class Box extends JPanel { 
    Color color; 

    public Box (Color c, int w, int h) { 
    color = color; 
    setSize(w, h); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
    g.setColor(color); 
    g.drawOval(0, 0, getWidth(), getHeight()); 
} 

... 

這不正是像上面的代碼,但希望它會讓你在正確的方向開始!

快速註釋(原始回覆):上面的示例ViewJFrame,它永遠不可見。相反,使用類變量gameWindow。將頂級課程設置爲可見窗口是一種很好的做法。

相關問題