Search code examples
javaswinggraphics2d

How to create a method in other class drawing on JPanel


My goal: create a method of class Point (code at the bottom), that allows me to draw multiple points (and lines in the future), so it looks like this:

Point pointA = new Point(0,0);
Point pointB = new Point(10,20);
pointA.draw(); // or probably: pointA.draw(someSurface);
pointB.draw();

I took code from a tutorial and modified it.

I found many similar problems while searching for answer, but either none of them had the answer for my case or I couldn't implement it.

As you can see below, I tried to create the method both inside the Point class and inside the Surface class (commented code), but without success.

What is the problem and what should I fix in my code?

Main:

public class Main {
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                BasicGraphics ex = new BasicGraphics();
                ex.setVisible(true);
                Point pointA = new Point(0,0);
                Point pointB = new Point(10,10);
                pointA.draw(ex.currentSurface);
                pointB.draw(ex.currentSurface);
            }
        });
    }
}

BasicGraphics:

public class BasicGraphics extends JFrame {
    public Surface currentSurface;
    public BasicGraphics() {
        initUI();
    }
    private void initUI() {
        currentSurface=new Surface();
        add(currentSurface);
        setTitle("My points");
        setSize(100, 100);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

Surface:

class Surface extends JPanel {

    /*public void drawPoint(Graphics g, Point givenPoint) {
        //I want to represent points as little circles
        Ellipse2D circle = new Ellipse2D.Double(); 
        Graphics2D g2d = (Graphics2D) g;
        circle.setFrameFromCenter(givenPoint.x, givenPoint.y, 10,10);
        g2d.draw(circle);
    }*/
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
    }
}

Point:

public class Point {
    public double x;
    public double y;
    public Point(double newX, double newY){
        x=newX;
        y=newY;
    }

public void draw(Surface givenSurface){
    Graphics g = givenSurface.getGraphics();
    Ellipse2D circle = new Ellipse2D.Double();
    Graphics2D g2d = (Graphics2D) g;
    circle.setFrameFromCenter(x, y, 10,10);
    g2d.draw(circle);
    givenSurface.paint(g2d);
    //givenSurface.drawPoint(g2d,this);
    //givenSurface.repaint();
    }
}

edit: Solutions, thanks to camickr. That's not the most elegant way I can imagine, but it works:

draw method in Point:

public void draw(Surface givenSurface){
        givenSurface.pointsList.add(this);
}

Surface class:

class Surface extends JPanel {

    public ArrayList<Point> pointsList = new ArrayList<>();

    private void drawPoints(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        double diameter = 10;
        for (Point currentPoint : pointsList) {
            Ellipse2D circle = new Ellipse2D.Double(currentPoint.x - diameter / 2, currentPoint.y - diameter / 2, diameter, diameter);
            g2d.fill(circle);
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        drawPoints(g);
    }

}

Solution

  • create a method of class Point (code at the bottom), that allows me to draw multiple points (and lines in the future).

    All custom painting needs to be done in the paintComponent() method of the panel. So every time the panel is painted the points/lines are repainted.

    So if you want to paint multiple object you need to:

    1. Create an ArrayList of the Object you want to paint
    2. Create a method to add Objects to this list
    3. In the paintComponent() method you iterate through the list and paint each Object.

    Check out the DrawOnCompont example from Custom Painting Approaches. It shows how you can dynamically add Rectangle to be painted.