我不知道它为什么不显示。首先,我创建一个组件实例,然后将其添加到二维JPanel数组中的某个元素。然后我循环遍历该数组并将每个JPanel添加到另一个JPanel容器中,该容器将容纳所有JPanel。
然后我将最终容器添加到我的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 :(得分: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 :(得分: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());
}
...
这与上面的代码不完全一样,但希望它能让你开始朝着正确的方向前进!
快速说明(原始回复):上面的示例View
是JFrame
,永远不会显示。而是使用类变量gameWindow
。将顶级类视为可见窗口是一种好习惯。