component.paint(Graphics)如何使用?什么原理?
我是j2se初学者在做程序时候遇到一个问题。
我在用
jpanel.paint(g)
的时候,将jpanel的组件画在一个bufferImage上。
但是画的时候,会把画面其他的实时更新的组件,一起画在图片上,都是左上角重叠的画出来的。
不太了解paint的原理,以及为什么我用的jpanel.paint(g),能把jpanel以外的组件也画在图片上,
实在搞不明白。
希望有经验的前辈们能给与帮助,谢谢! --------------------编程问答--------------------
--------------------编程问答--------------------
paint(Graphics g)会调用以下三个方法
-paintComponent:绘制组件(JPanel一般重写此方法)
-paintChildren :绘制此组件的子组件
-paintBorder :绘制组件的边框
噢,那也没有绘制我传入的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。
--------------------编程问答-------------------- public void paint(Graphics g)
由 Swing 调用,以绘制组件。应用程序不应直接调用 paint,而是应该使用 repaint 方法来安排重绘组件。
看下这篇文章,也许会清楚一些了。
http://www.doc88.com/p-295203521893.html --------------------编程问答--------------------
谢谢,的确让我了解了很多。
不过对于我现在的水平,还是不能解决我现在的问题。
按照你给的文章的理解,应该是我调用的paint(g)方法,把所有放在2级缓存的内容都画在了bufferedImage上,
是么?
我还是不太理解,我明明只用一个JPanel对象调用的paint(g)方法,应该只会把这个JPanel对象的内容画在bufferedImage上的,为什么其他的组件的变化也会画在同一个bufferedImage上。。
还是希望能帮助分析下,谢谢!~ --------------------编程问答-------------------- 楼主看api文档吧:
此方法实际上将绘制工作委托给三个受保护的方法:paintComponent、paintBorder 和 paintChildren。按列出的顺序调用这些方法。
所以执行paint实际上等于执行了下面三个方法paintComponent、paintBorder 、paintChildren
其中的paintChildren是绘制此组件的子组件,所以把jpanel上的其它组件也绘制了。
如果楼主只要绘制jpanel,那不要用paint方法,用paintComponent方法试试。 --------------------编程问答--------------------
我是打印panel和panel上的组件,
但是打印的时候,其他panel上的自动更新的组件也画上去了。。
代码没法贴。只能靠各位想想了。。不好意思。。
--------------------编程问答-------------------- 有没有人能帮助分析解决下啊!!! --------------------编程问答-------------------- 上面已经说了,不要有paint方法。
楼主倒底是打印组件,还是绘制组件?
打印用 printComponents(Graphics g),绘制用paintComponents(Graphics g) --------------------编程问答-------------------- 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);
}
}
}
看了paint,貌似没有发现会连带更新兄弟组件的地方
可能哪里出了问题,不过代码不贴的话很难分析啊 --------------------编程问答--------------------
额,不好意思,那个paint(Graphics g)API说叫打印,我其实是把画面的一部分保存成图片。
试过paintComponents(Graphics g)了,依旧保存的图片上还是多出来了其他panel的label和button了。
问题已用其他方式解决,但是的确还是不知道为什么会在图片上出现其他组件。 --------------------编程问答--------------------
的确是,但是代码太多太杂了。我也不方便贴上来。我自己继续看看api的代码和楼上贴的代码研究下吧。
问题用别的方式解决了,但是依旧不明白为什么之前的问题会出现,我会好好看看大家给的资料和建议的。
谢谢。 --------------------编程问答--------------------
if(getParent() != null && !(getParent() instanceof JComponent)) {
adjustPaintFlags();
shouldClearPaintFlags = true;
}
我会好好看看的,之前debug进到这个方法了。但是没太看懂。 --------------------编程问答--------------------
--------------------编程问答--------------------
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;
}
}
}
你可以试着模拟出一段同样带这个问题,但是独立又简单的程序。
看adjustPaintFlags方法中
它会上溯那些是JComponent的父类组件,并
if(jparent.getFlag(IS_PRINTING_ALL))
setFlag(IS_PRINTING_ALL, true);
感觉和这个可能有关
补充:Java , Java SE