JPanel中paint与paintComponent方法的区别及使用疑问
JPanel中paint与paintComponent的区别及你的棋盘绘制问题解答
一、这两个方法会自动执行吗?
- 正常情况下,Swing组件在需要重绘(首次显示、窗口调整大小、手动调用
repaint())时,会自动触发paint方法。 - 但你重写了
paint却没有调用super.paint(g),这直接破坏了Swing的绘制流程——原本paint会依次调用paintComponent、paintBorder、paintChildren三个方法,现在你跳过了这些调用,所以你的paintComponent方法根本不会被执行。 - 如果正确重写
paintComponent且没有错误覆盖paint方法,它会被paint自动调用。
二、是否建议合并?必须合并,且只保留paintComponent
Swing的绘制体系分工明确:
paint是AWT遗留的顶层绘制方法,在Swing组件中它的核心职责是调度三个子步骤:绘制组件自身内容(paintComponent)、绘制边框(paintBorder)、绘制子组件(paintChildren)。paintComponent才是Swing组件用来绘制自身内容的正确入口,所有自定义绘制逻辑都应该放在这里。
重写paint会导致很多潜在问题:比如子组件无法显示、组件背景不自动清除、边框失效等,所以绝对不建议重写JPanel的paint方法,把所有绘制逻辑合并到paintComponent里即可。
三、合并后为什么会出现覆盖?怎么解决?
你之前合并出现覆盖,大概率是没调用super.paintComponent(g)。这行代码的关键作用是:
- 清除组件之前的绘制内容,避免新旧图形重叠
- 绘制组件的背景色(如果已设置)
- 完成Swing内部的绘制初始化工作
正确的做法是:在paintComponent的第一行就调用super.paintComponent(g),然后再编写自定义绘制逻辑。
修正后的棋盘代码示例
package main; import javax.swing.JPanel; import java.awt.Graphics; import java.awt.Color; public class Panell extends JPanel { public Panell() { // 可设置组件初始大小,也可交由布局管理器处理 setSize(400, 400); } @Override public void paintComponent(Graphics g) { // 必须先调用父类方法,完成初始化和清除工作 super.paintComponent(g); // 绘制棋盘边框(8个15px格子总宽度120,和格子尺寸对齐) g.drawRect(100, 100, 120, 120); // 绘制棋盘格子,偏移1px避免被边框覆盖 boolean white = true; for(int y=0; y<8; y++){ for(int x=0; x<8; x++){ g.setColor(white ? new Color(235, 235, 208) : new Color(119, 148, 85)); g.fillRect(101 + x*15, 101 + y*15, 14, 14); white = !white; } white = !white; } } }
核心要点总结
- 永远只重写
paintComponent来做自定义绘制,不要修改paint方法。 - 必须在
paintComponent开头调用super.paintComponent(g),否则会出现绘制重叠、脏残留等问题。 - Swing的绘制流程是自动调度的,你只需要实现
paintComponent里的内容即可。
内容的提问来源于stack exchange,提问作者Tutusaus
相关产品推荐
相关产品推荐

