minolee minolee - 6 months ago 19
Java Question

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

Answer

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.

Comments