自定义绘制Swing组件,多次调用重绘

时间:2015-09-28 03:59:08

标签: java swing repaint

private void moveSquare(int x, int y) {
    int OFFSET = 1;
    if ((squareX!=x) || (squareY!=y)) {
        repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
        squareX=x;
        squareY=y;
        repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
    } 
}

在上面的代码中(完整代码可以在"执行自定义绘画" Java教程)的Demo App中找到,第一个repaint方法应该在前一个正方形的位置,第二个repaint应该在新正方形的位置绘制另一个正方形。但这实际上并没有发生。相反,前一个方块消失了,新的方块被涂上了。

当前一个方块消失时,新方块是如何绘制的?

3 个答案:

答案 0 :(得分:1)

您链接的文档可以回答您的问题,至少在一般情况下如此:

  

尽管我们在同一个事件处理程序中连续两次调用repaint,但Swing足够聪明,可以在一次绘制操作中获取该信息并重新绘制屏幕的这些部分。

当你致电repaint时,你实际上并没有画任何东西,但是在将来的某个时间要求重新制作

虽然repaint JavaDoc没有详细说明,但它包含指向" Painting in AWT and Swing"的链接,其中包含" {{3 }}"第二部分,第二部分适用于此:

  

(B)[当]绘画请求来自对repaint()扩展名javax.swing.JComponent的调用时:

     

JComponent.repaint()向组件RepaintManager注册一个异步重绘请求,该请求使用invokeLater()Runnable进行排队,以便稍后处理事件调度请求线程。

后来在那一节:

  

注意:如果在处理重绘请求之前在组件或其任何Swing祖先上发生多次repaint()调用,那么这些多个请求可能会折叠成单个回调到paintImmediately() [。 ..]

当您的事件处理程序返回时,JPanel的某些部分将被标记为重新绘制,可能是所有部分。这些被称为"脏区"。 Swing(最终)立刻重新绘制所有脏区域,并且只重复一次。在事件处理程序返回后,发生了这个绘画 - 意味着JPanel的外观已经改变了 - 所以彩色方块出现在新的位置,没有任何"剩菜和#34;在它的旧位置。

简而言之,不要将repaint视为"立即重新粉饰此区域",但是"将此区域添加到您的一些东西到后面的东西 - #34;。

答案 1 :(得分:1)

致电repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET); 后,它不会立即重新绘制该组件。但它添加了在EDT中的事件队列中再次绘制组件的请求。

每个代码行中发生的事情都在下面进行了解释..

(squareX,squareY,squareW+OFFSET,squareH+OFFSET)

标记由正方形RepaintManager限定的区域将重新绘制。但是在squareX=x; squareY=y; 这样做之前不会重新粉刷。

squareX

更改squareYrepaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET); 的值。但它不会改变之前标记的区域以进​​行重新绘制。现在,要重新绘制的区域是先前的值。

(squareX,squareY,squareW+OFFSET,squareH+OFFSET)

标记由正方形RepaintManager限定的区域将重新绘制。现在有两个部分RepaintManager必须重新绘制。以前的广场和新广场。但是在RepaintManager这样做之前不会重新粉刷。

最后,到时候,protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawString("This is my custom Panel!",10,20); g.setColor(Color.RED); g.fillRect(squareX,squareY,squareW,squareH); g.setColor(Color.BLACK); g.drawRect(squareX,squareY,squareW,squareH); } 绘制组件。

repaint()

现在该组件仅绘制了2个区域。 (上一个方块和新方块)但红色方块只能在新方块内绘制。在旧广场上没有什么可画的。所以先前绘制的东西将被删除..

实际上,虽然paintComponents()有2个方法调用,但RepaintManager只会被调用一次。要重新绘制的总面积由paintComponents()处理,gridApi仅调用一次..

答案 2 :(得分:0)

Oracle docs给出了很好的解释:  defaultdict方法不是一次调用重绘方法,而是调用两次。第一次调用告诉Swing重新绘制先前正方形的组件区域(继承的行为使用UI委托用当前背景颜色填充该区域。)第二次调用绘制当前正方形的组件区域