java重绘多个区域

时间:2016-05-31 13:47:03

标签: java swing

我想在JPanel上绘制特定区域,就像这样(黑色区域是我想要重新绘制JPanel的地方):

enter image description here

下面的代码是我如何实现这一点。它跟随鼠标光标并在鼠标光标点处绘制一个圆圈。框架和面板的尺寸为300 * 300。

public class MiniGraphicTest extends JPanel{

private static final long serialVersionUID = 1L;

public int x,y;
public MiniGraphicTest() {
    super();
    x = -1;
    y = -1;
    addMouseMotionListener(new MouseMotionAdapter(){
        @Override
        public void mouseMoved(MouseEvent m){
            x = m.getX()-25;
            y = m.getY()-25;
            repaint(100,100,100,100);
            repaint(200,200,100,100);
        }
    });
}
protected void paintComponent(Graphics g){
    super.paintComponent(g);
    //////////////////////
    //DO NOT MODIFY HERE//
    //////////////////////
    //Draw gridline
    int width = this.getWidth();
    int height = this.getHeight();
    g.setColor(Color.BLACK);
    for(int i=100;i<width;i+=100){
        g.drawLine(i, 0, i, height);
    }
    for(int i=100;i<height;i+=100){
        g.drawLine(0, i, width, i);
    }
    //////////////////////
    //put test code here//
    //////////////////////
    if(x == -1&&y==-1) return;//initially draw nothing
    g.fillOval(x, y, 50, 50);
}
}//main function is just showing the panel. nothing special
public static void main(String[] args) {
    JFrame jf = new JFrame("Test");
    MiniGraphicTest test = new MiniGraphicTest();
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    test.setPreferredSize(new Dimension(300, 300));
    jf.setResizable(false);
    jf.add(test);
    jf.pack();
    jf.setVisible(true);
}

此代码的结果如下:

enter image description here

重绘在该区域之外进行重新粉刷。你能解释一下为什么会发生这种情况以及如何解决这个问题吗?

PS。当在mouseMoved中只调用单个重绘(100,100,100,100)时,代码完全有效。

谢谢

2 个答案:

答案 0 :(得分:1)

我认为 Fast Snail 的解决方案通常是正确的答案。如果你有一个动态大小的电路板左右,你可以考虑只有当鼠标在所需的正方形内时才能画圆圈。

多次通话repaint只占repaint的更大区域,以包含您在repaint的多次通话中指定的所有区域。

但是如果你有这个带有9个单元的小板,我认为可以快速解决你的情况,以免后续调用repaint

public class MiniGraphicTest extends JPanel {

    private static final long serialVersionUID = 1L;

    public int x, y;
    boolean flag;

    public MiniGraphicTest() {
        super();
        x = -1;
        y = -1;
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseMoved(MouseEvent m) {
                x = m.getX() - 25;
                y = m.getY() - 25;
                if(flag) {
                    repaint(100, 100, 100, 100);
                } else {
                    repaint(200, 200, 100, 100);
                }
                flag = !flag;
            }
        });
    }
    // Other codes of yours
}

祝你好运。

答案 1 :(得分:0)

repaint()仅标记要在EDT中重新绘制的组件。 后续调用不会改变任何内容。

使用坐标(矩形)调用repaint标记仅在rect内重新绘制的组件。 后续调用只能更改(扩展)该矩形。

如果您希望clip绘制到某个区域,则需要在paintComponent方法中指定。