component.paint(Graphics)如何使用?什么原理?

suqin1983_3 2012-08-13 01:58:11
我是j2se初学者
在做程序时候遇到一个问题。
我在用
jpanel.paint(g)
的时候,将jpanel的组件画在一个bufferImage上。
但是画的时候,会把画面其他的实时更新的组件,一起画在图片上,都是左上角重叠的画出来的。
不太了解paint的原理,以及为什么我用的jpanel.paint(g),能把jpanel以外的组件也画在图片上,
实在搞不明白。
希望有经验的前辈们能给与帮助,谢谢!
...全文
371 15 打赏 收藏 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
dracularking 2012-08-16
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 的回复:]

引用 10 楼 的回复:

引用 7 楼 的回复:

有没有人能帮助分析解决下啊!!!

看了paint,貌似没有发现会连带更新兄弟组件的地方

可能哪里出了问题,不过代码不贴的话很难分析啊

的确是,但是代码太多太杂了。我也不方便贴上来。我自己继续看看api的代码和楼上贴的代码研究下吧。
问题用别的方式解决了,但是依旧不明白为什么之前的问题会出现,我会好好看看大家给的……
[/Quote]
你可以试着模拟出一段同样带这个问题,但是独立又简单的程序。

看adjustPaintFlags方法中
它会上溯那些是JComponent的父类组件,并
if(jparent.getFlag(IS_PRINTING_ALL))
setFlag(IS_PRINTING_ALL, true);

感觉和这个可能有关
dracularking 2012-08-16
  • 打赏
  • 举报
回复

private void adjustPaintFlags() {
JComponent jparent = null;
Container parent;
for(parent = getParent() ; parent != null ; parent =
parent.getParent()) {
if(parent instanceof JComponent) {
jparent = (JComponent) parent;
if(jparent.getFlag(ANCESTOR_USING_BUFFER))
setFlag(ANCESTOR_USING_BUFFER, true);
if(jparent.getFlag(IS_PAINTING_TILE))
setFlag(IS_PAINTING_TILE, true);
if(jparent.getFlag(IS_PRINTING))
setFlag(IS_PRINTING, true);
if(jparent.getFlag(IS_PRINTING_ALL))
setFlag(IS_PRINTING_ALL, true);
break;
}
}
}
brightyq 2012-08-15
  • 打赏
  • 举报
回复
上面已经说了,不要有paint方法。

楼主倒底是打印组件,还是绘制组件?
打印用 printComponents(Graphics g),绘制用paintComponents(Graphics g)
suqin1983_3 2012-08-15
  • 打赏
  • 举报
回复
有没有人能帮助分析解决下啊!!!
suqin1983_3 2012-08-15
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

in JComponent.java
Java code

public void paint(Graphics g) {
boolean shouldClearPaintFlags = false;

if ((getWidth() <= 0) || (getHeight() <= 0)) {
return;
}

……
[/Quote]
if(getParent() != null && !(getParent() instanceof JComponent)) {
adjustPaintFlags();
shouldClearPaintFlags = true;
}
我会好好看看的,之前debug进到这个方法了。但是没太看懂。
suqin1983_3 2012-08-15
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

引用 7 楼 的回复:

有没有人能帮助分析解决下啊!!!

看了paint,貌似没有发现会连带更新兄弟组件的地方

可能哪里出了问题,不过代码不贴的话很难分析啊
[/Quote]
的确是,但是代码太多太杂了。我也不方便贴上来。我自己继续看看api的代码和楼上贴的代码研究下吧。
问题用别的方式解决了,但是依旧不明白为什么之前的问题会出现,我会好好看看大家给的资料和建议的。
谢谢。
suqin1983_3 2012-08-15
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]

上面已经说了,不要有paint方法。

楼主倒底是打印组件,还是绘制组件?
打印用 printComponents(Graphics g),绘制用paintComponents(Graphics g)
[/Quote]
额,不好意思,那个paint(Graphics g)API说叫打印,我其实是把画面的一部分保存成图片。
试过paintComponents(Graphics g)了,依旧保存的图片上还是多出来了其他panel的label和button了。
问题已用其他方式解决,但是的确还是不知道为什么会在图片上出现其他组件。
dracularking 2012-08-15
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

有没有人能帮助分析解决下啊!!!
[/Quote]
看了paint,貌似没有发现会连带更新兄弟组件的地方

可能哪里出了问题,不过代码不贴的话很难分析啊
dracularking 2012-08-15
  • 打赏
  • 举报
回复
in JComponent.java

public void paint(Graphics g) {
boolean shouldClearPaintFlags = false;

if ((getWidth() <= 0) || (getHeight() <= 0)) {
return;
}

Graphics componentGraphics = getComponentGraphics(g);
Graphics co = componentGraphics.create();
try {
RepaintManager repaintManager = RepaintManager.currentManager(this);
Rectangle clipRect = co.getClipBounds();
int clipX;
int clipY;
int clipW;
int clipH;
if (clipRect == null) {
clipX = clipY = 0;
clipW = getWidth();
clipH = getHeight();
}
else {
clipX = clipRect.x;
clipY = clipRect.y;
clipW = clipRect.width;
clipH = clipRect.height;
}

if(clipW > getWidth()) {
clipW = getWidth();
}
if(clipH > getHeight()) {
clipH = getHeight();
}

if(getParent() != null && !(getParent() instanceof JComponent)) {
adjustPaintFlags();
shouldClearPaintFlags = true;
}

int bw,bh;
boolean printing = getFlag(IS_PRINTING);
boolean repainting = getFlag(IS_REPAINTING);
if(!printing && repaintManager.isDoubleBufferingEnabled() &&
!getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered() &&
(repaintManager.isPainting() || repainting)) {
repaintManager.beginPaint();
try {
repaintManager.paint(this, this, co, clipX, clipY, clipW,
clipH);
} finally {
repaintManager.endPaint();
}
}
else {
// Will ocassionaly happen in 1.2, especially when printing.
if (clipRect == null) {
co.setClip(clipX, clipY, clipW, clipH);
}

if (!rectangleIsObscured(clipX,clipY,clipW,clipH)) {
if (!printing) {
paintComponent(co);
paintBorder(co);
}
else {
printComponent(co);
printBorder(co);
}
}
if (!printing) {
paintChildren(co);
}
else {
printChildren(co);
}
}
} finally {
co.dispose();
if(shouldClearPaintFlags) {
setFlag(ANCESTOR_USING_BUFFER,false);
setFlag(IS_PAINTING_TILE,false);
setFlag(IS_PRINTING,false);
setFlag(IS_PRINTING_ALL,false);
}
}
}
suqin1983_3 2012-08-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
楼主看api文档吧:
此方法实际上将绘制工作委托给三个受保护的方法:paintComponent、paintBorder 和 paintChildren。按列出的顺序调用这些方法。

所以执行paint实际上等于执行了下面三个方法paintComponent、paintBorder 、paintChildren
其中的paintChildren是绘制此组件的子组件,所以把jpanel上的其……
[/Quote]
我是打印panel和panel上的组件,
但是打印的时候,其他panel上的自动更新的组件也画上去了。。
代码没法贴。只能靠各位想想了。。不好意思。。
brightyq 2012-08-14
  • 打赏
  • 举报
回复
楼主看api文档吧:
此方法实际上将绘制工作委托给三个受保护的方法:paintComponent、paintBorder 和 paintChildren。按列出的顺序调用这些方法。

所以执行paint实际上等于执行了下面三个方法paintComponent、paintBorder 、paintChildren
其中的paintChildren是绘制此组件的子组件,所以把jpanel上的其它组件也绘制了。

如果楼主只要绘制jpanel,那不要用paint方法,用paintComponent方法试试。
suqin1983_3 2012-08-14
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
public void paint(Graphics g)
由 Swing 调用,以绘制组件。应用程序不应直接调用 paint,而是应该使用 repaint 方法来安排重绘组件。


看下这篇文章,也许会清楚一些了。
http://www.doc88.com/p-295203521893.html
[/Quote]
谢谢,的确让我了解了很多。
不过对于我现在的水平,还是不能解决我现在的问题。
按照你给的文章的理解,应该是我调用的paint(g)方法,把所有放在2级缓存的内容都画在了bufferedImage上,
是么?
我还是不太理解,我明明只用一个JPanel对象调用的paint(g)方法,应该只会把这个JPanel对象的内容画在bufferedImage上的,为什么其他的组件的变化也会画在同一个bufferedImage上。。

还是希望能帮助分析下,谢谢!~
brightyq 2012-08-13
  • 打赏
  • 举报
回复
public void paint(Graphics g)
由 Swing 调用,以绘制组件。应用程序不应直接调用 paint,而是应该使用 repaint 方法来安排重绘组件。


看下这篇文章,也许会清楚一些了。
http://www.doc88.com/p-295203521893.html
suqin1983_3 2012-08-13
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
Java code


paint(Graphics g)会调用以下三个方法
-paintComponent:绘制组件(JPanel一般重写此方法)
-paintChildren :绘制此组件的子组件
-paintBorder :绘制组件的边框
[/Quote]

噢,那也没有绘制我传入的jpanel以外组件的功能吧?
比如我用的 JPanel a 的 paint方法
JPanel a 包含一个JLabel al
但是还有同层的JPanel b
JPanel b 中包含 了 JLabel bl
bl是每秒都会更换背景图片的
创建一个BufferImage bi
取得bi的 Graphics big
使用 a.paint(big),并且每秒都会创建一个新的bi 去画。
理论上应该在 bi上画出来 a 和 al
但是却多出来 bl了。。
为什么呢?

看到出来的图片的效果,我会觉得 虽然用的是a的paint,
但是每次画的时候,都是a上面不停地画出来 bl,而且也画出了上次画的al。



FFF9527 2012-08-13
  • 打赏
  • 举报
回复

paint(Graphics g)会调用以下三个方法
-paintComponent:绘制组件(JPanel一般重写此方法)
-paintChildren :绘制此组件的子组件
-paintBorder :绘制组件的边框

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧