Java Swing中JPanel叠加绘制图形内容消失的问题求助
问题原因
你遇到的问题根源在于BorderLayout的布局规则:当调用contentPane.add(component)时,默认是将组件添加到CENTER区域,而这个区域同一时间只能显示一个组件——后添加的组件会直接替换掉之前的,所以你只能看到最后添加的那个。
解决方案
下面提供两种最适合你需求的修复方式:
方式一:合并绘制逻辑(推荐)
既然背景和方块都是绘制类组件,直接把它们的绘制逻辑合并到同一个自定义JComponent中,彻底避免组件覆盖问题:
import java.awt.*; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.*; public class App { public static void main(String[] args) throws Exception { MainFrame myFrame = new MainFrame(); myFrame.init(); } } class MainFrame extends JFrame{ public void init(){ try { Image logo = ImageIO.read(new File("Logo.jpg")); setIconImage(logo); } catch (IOException e) { e.printStackTrace(); } setTitle("Sandsim"); setSize(600, 600); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // 使用合并了背景和方块的组件 GamePanel gamePanel = new GamePanel(); setContentPane(gamePanel); setVisible(true); } } // 合并背景和方块绘制的组件 class GamePanel extends JComponent { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // 必须调用,确保组件绘制流程正确 Graphics2D g2d = (Graphics2D) g; int gridSize = 10; // 绘制背景网格 g2d.setColor(Color.BLACK); // 竖线 for (int x = 0; x < getWidth(); x += gridSize) { g2d.drawLine(x, 0, x, getHeight()); } // 横线 for (int y = 0; y < getHeight(); y += gridSize) { g2d.drawLine(0, y, getWidth(), y); } // 绘制方块(后续可改为鼠标点击生成的坐标列表) g2d.setColor(Color.YELLOW); g2d.fillRect(10, 10, gridSize, gridSize); } }
方式二:使用分层窗格(JLayeredPane)
如果想保留分开的组件类,可以用JLayeredPane分层放置,背景在底层,方块在顶层:
import java.awt.*; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.*; public class App { public static void main(String[] args) throws Exception { MainFrame myFrame = new MainFrame(); myFrame.init(); } } class MainFrame extends JFrame{ public void init(){ try { Image logo = ImageIO.read(new File("Logo.jpg")); setIconImage(logo); } catch (IOException e) { e.printStackTrace(); } setTitle("Sandsim"); setSize(600, 600); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); JLayeredPane layeredPane = new JLayeredPane(); layeredPane.setPreferredSize(new Dimension(600,600)); setContentPane(layeredPane); Background background = new Background(); background.setBounds(0,0,600,600); Sand sand = new Sand(); sand.setBounds(0,0,600,600); sand.setOpaque(false); // 关键:让方块组件透明,不遮挡背景 // 背景放在底层,方块放在顶层 layeredPane.add(background, JLayeredPane.DEFAULT_LAYER); layeredPane.add(sand, JLayeredPane.PALETTE_LAYER); setVisible(true); } } class Background extends JComponent { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; g2d.setColor(Color.BLACK); int positionX = 0; int positionY = 0; for (int i = 0; i < getBounds().width / 10; i++) { g2d.drawLine(positionX, 0, positionX, getBounds().height); positionX += 10; } for (int i = 0; i < getBounds().height / 10; i++) { g2d.drawLine(0, positionY, getBounds().width, positionY); positionY += 10; } } } class Sand extends JComponent{ @Override protected void paintComponent(Graphics g){ super.paintComponent(g); Graphics2D g2d =(Graphics2D)g; g2d.setColor(Color.YELLOW); g2d.fillRect(10, 10, 10, 10); } }
后续扩展建议
如果要实现鼠标点击生成方块,可以在主绘制组件中添加鼠标监听器:
- 维护一个
List<Point>存储所有方块的网格坐标 - 在
mouseClicked事件中计算鼠标所在的网格位置,添加到列表 - 在
paintComponent中遍历列表,批量绘制所有方块
内容的提问来源于stack exchange,提问作者Wurstbrot
相关产品推荐
相关产品推荐

