Mohit Rai Mohit Rai - 2 months ago 9
Java Question

Painted JPanel gets flushed every time the window is minimized or dragged out of screen

I am drawing a grid on a JPanel by overriding paint(g) and with it marking some points whichever clicked on the grid, but the main problem is, if someone minimize the grid or drag it around the screen, the part of the screen goes blank. I can't figure out how to change my code to have it refreshed every time the screen is minimized or dragged around, please help me with the code.

Here is my code:-

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

public class draw extends JPanel {

private int x,y,X,Y,xmin,xmax,ymin,ymax;
private int clickParam = 0;
private double d, theta;
private ArrayList<Integer> ab = new ArrayList<Integer>();
private ArrayList<Integer> or = new ArrayList<Integer>();
private ArrayList<Double> distance = new ArrayList<Double>();
private ArrayList<Double> angle = new ArrayList<Double>();
Graphics2D g2d = null;

public void drawing(){

repaint();

}
@Override
public void paintComponent(Graphics g){

super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;

g2d = g2;
int stroke[]={1,2,3,4,5};

g2.setStroke(new BasicStroke(stroke[1]));
xmin = 150;
ymin = 150;
xmax = 650;
ymax = 650;
int xsize = xmax - xmin;
int ysize = ymax - ymin;
g2.drawRect(xmin, ymin, xsize, ysize);
for(int i=50;i<=xsize;i+=50){

g2.drawLine(xmin+i, ymin, xmin+i, ymax);
g2.drawLine(xmin, ymin+i, xmax, ymin+i);

}
g2.setStroke(new BasicStroke(stroke[0]));
for(int i=10;i<=xsize;i+=10){

g2.drawLine(xmin+i, ymin, xmin+i, ymax);
g2.drawLine(xmin, ymin+i, xmax, ymin+i);

}

}
public void drawPoints(Graphics2D g2){

if(x >= xmin && x <= xmax && y >= ymin && y <= ymax)
g2.fillOval(x-3, y-3, 7, 7);

}
public void onClick(){

addMouseListener(new MouseAdapter(){

@Override
public void mousePressed(MouseEvent e){

setxy(e);
setXY();
clickParam = 2;
drawPoints(g2d);

if(x >= xmin && x <= xmax && y >= ymin && y <= ymax){

setDistance();
setAngle();
display();
}
}

});

}
public void setxy(MouseEvent e){

x = e.getX();
y = e.getY();
if(x >= xmin && x <= xmax && y >= ymin && y <= ymax){
ab.add(x);
or.add(y);
}
}
public void setXY(){

X = x - xmin;
Y = ymax - y;

}
public void setDistance(){

d = Math.sqrt(Math.pow(X/10, 2) + Math.pow(Y/10, 2));
distance.add(d);

}
public void setAngle(){

theta = Math.atan2(Y,X)*180/Math.PI;
angle.add(theta);

}
public void display(){

System.out.println("(X,Y) = ("+(X/10)+","+(Y/10)+")"+" & (d,theta) = ("+d+","+theta+")");

}
}


and the main class:-

import java.awt.Dimension;
import javax.swing.*;

public class mainClass {

public static void main(String args[]){
JFrame jframe = new JFrame("TEST");
draw d = new draw();
jframe.setPreferredSize(new Dimension(1000,1000));
jframe.pack();
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.add(d);
jframe.setVisible(true);
jframe.setResizable(false);
d.drawing();
d.onClick();


}

}

Answer
  1. onClick is never called, therefore the MouseListener is never added.
  2. Create a list of Points and loop through it in your paintComponent method.
  3. drawPoints should only be called inside the paintComponent method, since it takes the current Graphics2D object.

Restructured code:

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

public class Draw extends JPanel { // Class names should start with an uppercase letter

    private int xmin, xmax, ymin, ymax;
    private ArrayList<Point> points = new ArrayList<Point>(); // Create a list where all clicked points will be stored

    public Draw() {
        xmin = 150;
        ymin = 150;
        xmax = 650;
        ymax = 650;
        addMouseListener(new MouseAdapter() { // Add MouseListener in the constructor
            @Override
            public void mousePressed(MouseEvent e) {
                Point point = new Point(e.getX(), e.getY());
                if (point.x >= xmin && point.x <= xmax && point.y >= ymin
                        && point.y <= ymax) {
                    points.add(point); // Add the point to the list
                    repaint();
                }
            }
        });
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;

        int stroke[] = { 1, 2, 3, 4, 5 };

        g2.setStroke(new BasicStroke(stroke[1]));
        int xsize = xmax - xmin;
        int ysize = ymax - ymin;
        g2.drawRect(xmin, ymin, xsize, ysize);
        for (int i = 50; i <= xsize; i += 50) {
            g2.drawLine(xmin + i, ymin, xmin + i, ymax);
            g2.drawLine(xmin, ymin + i, xmax, ymin + i);

        }
        g2.setStroke(new BasicStroke(stroke[0]));
        for (int i = 10; i <= xsize; i += 10) {
            g2.drawLine(xmin + i, ymin, xmin + i, ymax);
            g2.drawLine(xmin, ymin + i, xmax, ymin + i);

        }
        drawPoints(g2);
    }

    private void drawPoints(Graphics2D g2) {
        for (Point point : points) { // Loop through the list of points
            g2.fillOval(point.x - 3, point.y - 3, 7, 7);
        }
    }

    public static void main(String args[]) {
        JFrame jframe = new JFrame("TEST");
        Draw d = new Draw();
        jframe.setSize(800,800);
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jframe.setContentPane(d);
        jframe.setVisible(true);
    }

}