minolee
minolee

Reputation: 13

java repaint multiple area

I want to draw specific area on JPanel, like this (black area is where I want JPanel to be repainted):

enter image description here

Below code is how I implemented this. It follows mouse cursor and draws a circle at the mouse cursor point. The size of frame and panel is 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);
}

The result of this code is like this :

enter image description here

It repaints outside of the area to be repainted. Can you explain me why this happened and how to solve this?

PS. The code completely works well when only single repaint(100,100,100,100) is called in the mouseMoved.

Thank you

Upvotes: 1

Views: 226

Answers (2)

STaefi
STaefi

Reputation: 4377

I think Fast Snail's solution is is the right answer in general. If you have a dynamic situation with dynamic size of the board or so, you may consider draw circle only if mouse is inside the required squares as recommended.

Multiple calling repaint only makes a bigger area of repaint to include all the area's you specified in the multiple calls of repaint.

But if you have this little board with 9 cells, I think there is a quick fix for your situation in order not to make subsequent calls for 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
}

Good Luck.

Upvotes: 1

krzydyn
krzydyn

Reputation: 1032

repaint() only marks the component to be repainted in EDT. Subsequent calls not changes anything.

Calling repaint with coordinates (rectangle) mark the component to be repainted only inside the rect. Subsequent calls can only change (extend) that rect.

If you want to clip drawing to some area, you need to specify that in your paintComponent method.

Upvotes: 0

Related Questions