Java AWT:滚动窗格中的组件:仅重新绘制视口/可见区域

Java AWT:滚动窗格中的组件:仅重新绘制视口/可见区域,java,awt,scrollpane,Java,Awt,Scrollpane,我有一个扩展画布的自定义组件,我将其放置在滚动窗格中。当我的组件的内部状态改变时,我调用它的重绘方法。但是,这会导致完全重新绘制。传递给组件的绘制方法的图形对象的边界是组件的大小,而不是视口的大小。这是一个问题,因为组件可能变得非常大,10000+px,并且具有复杂的绘制逻辑 以下代码举例说明了此问题: package main; import java.awt.Canvas; import java.awt.Color; import java.awt.Graphics; import ja

我有一个扩展画布的自定义组件,我将其放置在滚动窗格中。当我的组件的内部状态改变时,我调用它的重绘方法。但是,这会导致完全重新绘制。传递给组件的绘制方法的图形对象的边界是组件的大小,而不是视口的大小。这是一个问题,因为组件可能变得非常大,10000+px,并且具有复杂的绘制逻辑

以下代码举例说明了此问题:

package main;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.ScrollPane;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;

public class ScrollPaneTest {
    static class MyCanvas extends Canvas {
        @Override
        public void paint(Graphics g) {
            super.paint(g);
            Rectangle clipBounds = g.getClipBounds();
            System.out.println("paint " + clipBounds.toString());
            g.setColor(Color.black);
            g.drawString(clipBounds.toString(), 20, 20);
        }

//      Attempted solution: doesn't work; MyCanvas.paint() doesn't get called at all.
//      @Override
//      public void repaint(long tm, int x, int y, int width, int height) {
//          System.out.println(tm + " " + x + " " + y + " "
//                  + width + " " + height);
//          getParent().repaint();
//      }

    }

    public static void main(String[] args) throws Exception {
        JFrame frame = new JFrame();
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent we) {
                System.exit(0);
            }
        });
        frame.setBounds(0, 0, 400, 200);
        frame.setVisible(true);

        ScrollPane pane = new ScrollPane();
        frame.add(pane);

        MyCanvas mc = new MyCanvas();
        pane.add(mc);
        mc.setBounds(0, 0, 1000, 1000);
        mc.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                System.out.println("keypressed");
                mc.repaint();
            }
        });
        mc.requestFocus();
    }
}
问题:当按下一个键并重新绘制时,调用paintGraphics,打印的剪贴簿始终包含整个MyCanvas:

paint java.awt.Rectangle[x=0,y=0,width=1000,height=1000]

而不仅仅是可见区域400x200。我搜索了Google/SO,但没有找到任何相关信息;有人知道如何更改此设置或在绘制方法中计算可见区域吗?

如果图形的剪裁边界未设置为视口区域,则需要检查滚动窗格的父对象是什么,然后检查其viewportSizeproperty@MadProgrammer有点像黑客;我想这就是我使用AWT xD所得到的。无论如何,谢谢!很多问题归结为这样一个事实:通常,组件的绘制是由操作系统本身完成的,而不是AWT,因此它的优化方式与Swing不同