如何使我的自定义Swing组件可见?

我不知道它为什么不显示。 首先,我创建一个组件实例,然后将其添加到二维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组件,它是否仍然具有相同的位置?

我尝试扩展JPanel,在我的菜单下有一个小的10×10像素灰盒子。 至少是一个开始

当您使用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); } } 

在过去,我通过扩展JPanel而不是JComponent来解决这个问题。 我在这里找到了一个很好的例子 这是一个改编它将绘制一个框:

 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 。 将顶级类视为可见窗口是一种好习惯。