Syed Imran
Syed Imran

Reputation: 11

Passing variable to paintComponent method

I need some help. How does it pass a variable from class Circle to the paintComponent method because I want to make the circle change the x, y, w, h based on user input. Is there any idea to fix this? Since the problem there is an error after I press the button it doesn't execute anything.

Based on this image.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.text.DecimalFormat;
import javax.swing.JLabel;
import javax.swing.JTextField;


public class Circle extends JFrame implements ActionListener{
    
     private JPanel p1,p2,p3,buttonsize;
     private JLabel title,lb1,lb2,lb3,lb4,lb5,lb6,lb7,lb8,lb9,lb10;
     private JTextField circle1x,circle1y,circle1r,circle2x,circle2y,circle2r;
     private JButton drawButton;
     static int x1=30,x2=200,y1=10,y2=10,r1=10,r2=10;
    
    public static void main(String[]args)
    {
        Circle c = new Circle();
        c.setSize(400,400);
        c.setTitle("Project");
        c.setVisible(true);
        c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    
    public Circle()
    {
       
        title = new JLabel("Two circles intersect? No");
        p1 = new JPanel();
        p1.add(title);

        p2 = new JPanel();
        //p2.add(new Circles());
        
        lb1 = new JLabel("Enter circle 1");
        lb2 = new JLabel("Enter circle 2");
        lb3 = new JLabel("info:");
        lb4 = new JLabel("info:");
        lb5 = new JLabel("Center x:");
        lb6 = new JLabel("Center y:");
        lb7 = new JLabel("Radius:");
        lb8 = new JLabel("Center x:");
        lb9 = new JLabel("Center y:");
        lb10 = new JLabel("Radius:");
        
        circle1x = new JTextField(1);
        circle1y = new JTextField(1);
        circle1r = new JTextField(1);
        circle2x = new JTextField(1);
        circle2y = new JTextField(1);
        circle2r = new JTextField(1);
        drawButton = new JButton("Redraw Circles");
        buttonsize = new JPanel();
        buttonsize.setSize(50,50);
        buttonsize.add(drawButton);
        p3 = new JPanel();
        p3.setLayout(new GridLayout(5,5));

        p3.add(lb1);p3.add(lb3);p3.add(new JLabel(""));p3.add(lb2);p3.add(lb4);
        p3.add(lb5);p3.add(circle1x);p3.add(new JLabel(""));p3.add(lb8);p3.add(circle2x);
        p3.add(lb6);p3.add(circle1y);p3.add(new JLabel(""));p3.add(lb9);p3.add(circle2y);
        p3.add(lb7);p3.add(circle1r);p3.add(new JLabel(""));p3.add(lb10);p3.add(circle2r);
        p3.add(new JLabel(""));p3.add(new JLabel(""));p3.add(drawButton);p3.add(new JLabel(""));p3.add(new JLabel(""));
        
        
        
        setLayout(new BorderLayout());
        //call the constructor of the panel
        add(p1,BorderLayout.NORTH);
        add(new Circles(),BorderLayout.CENTER);
        add(p3,BorderLayout.SOUTH);
        
        
        drawButton.addActionListener(this);
    }

     public void actionPerformed(ActionEvent e)
    {
        double c1x = Double.parseDouble(circle1x.getText());
        double c1y = Double.parseDouble(circle1y.getText());
        double c1r = Double.parseDouble(circle1r.getText());
        double c2x = Double.parseDouble(circle2x.getText());
        double c2y = Double.parseDouble(circle2y.getText());
        double c2r = Double.parseDouble(circle2r.getText());
        
        x1 = (int) c1x;
        x2 = (int) c2x;
        y1 = (int) c1y;
        y2 = (int) c2y;
        r1 = (int) c1r;
        r2 = (int) c2r;
        
        
        if(e.getSource()== drawButton){
               repaint();
        }
            
        }

    }

class Circles extends JPanel
{
    

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.setColor(Color.BLACK);
        g.drawOval(Circle.x1, Circle.y1, Circle.r1, Circle.r1);
        g.drawOval(Circle.x2, Circle.y2, Circle.r2, Circle.r2);
    }
}


Upvotes: 1

Views: 340

Answers (2)

Gilbert Le Blanc
Gilbert Le Blanc

Reputation: 51445

Introduction

This was a fun little project. Because it is a project, I'm not going to provide all the code I wrote. The reason I'm answering this question is to outline an approach to this Swing project or almost any Java project.

Here's the GUI I came up with. It's a bit different than the OP's picture.

Project GUI 1

Here's another example.

Project GUI 2

And another.

Project GUI 3

Explanation

When I create a Swing application, or most Java applications, I use the model / view / controller (MVC) pattern. This pattern allows me to separate my concerns and focus on one part of the application at a time.

In a Swing GUI, the MVC pattern means:

  1. The view reads information from the model.
  2. The view does not modify the model in any way.
  3. The controller updates the model and repaints / revalidates the view.

Model

Rather than explaining a model, I'll just show you the model I created.

public class IntersectingCirclesModel {
    
    private Circle[] circles;
    
    public IntersectingCirclesModel() {
        this.circles = new Circle[2];
    }

    public boolean isIntersects() {
        double distanceX = Math.abs(circles[0].getCenter().getX() - 
                circles[1].getCenter().getX()); 
        double distanceY = Math.abs(circles[0].getCenter().getY() - 
                circles[1].getCenter().getY()); 
        double distance1 = (distanceX * distanceX + distanceY * distanceY);
        
        double radius1 = circles[0].getRadius();
        double radius2 = circles[1].getRadius();
        double diameter = radius1 + radius2;
        double distance2 = diameter * diameter;
        
        System.out.println(distance1 + " " + distance2);
        return distance1 <= distance2;
    }

    public Circle[] getCircles() {
        return circles;
    }
    
    public void setCircle(Circle circle, int index) {
        this.circles[index] = circle;
    }
}

public class Circle {
    
    private int radius;
    
    private Point center;

    public int getRadius() {
        return radius;
    }

    public void setRadius(int radius) {
        this.radius = radius;
    }

    public Point getCenter() {
        return center;
    }

    public void setCenter(Point center) {
        this.center = center;
    }
    
    public void setCenter(int x, int y) {
        this.center = new Point(x, y);
    }
    
}

I created two plain Java getter / setter classes. The first class, the Circle class, holds a radius and a center point. I used a java.awt.Point to hold the center point.

The second class, the IntersectingCirclesModel class, is the application model. This class holds an array of two Circle instances and calculates whether or not the two Circle instances intersect.

The intersect calculation is pretty simple. The distance between the two center points has to be less than the distance of the two radii added together. I actually calculate the distance squared so I don't have to take square roots.

View

The view consists of one JFrame, one drawing JPanel, two instances of one entry JPanel, and a JPanel to hold the two instances of one entry JPanel and the JButton.

I use these Swing components. The only Swing component I extend is JPanel to create the drawing JPanel. I do this so I can override the paintComponent method. The first line in my paintComponent method is a call to the super paintComponent method to maintain the Swing paint chain.

I create the JFrame by creating the subordinate JPanels, packing the JFrame, and setting the JFrame visible.

The drawing JPanel is straightforward. I extend a JPanel. I pass an instance of the model class to the drawing JPanel. In the constructor, I set the background color and set the preferred size of the JPanel.

The paintComponent method checks to see if the two Circle instances have been created. If so, the circles are drawn and the intersect text at the top of the drawing JPanel is drawn.

The entry JPanel is a separate class. I do this so I only have to create one entry panel. The only difference between the two entry panels is the title, so I pass the title into the class through the constructor.

I create the entry JPanel using a GridBagLayout. The GridBagLayout is the layout to use when you want to create any JPanel that looks like a form.

I create a consolidating JPanel by creating two instances of the entry JPanel. This consolidating JPanel uses a FlowLayout.

I create an additional consolidating JPanel using a BorderLayout. This JPanel puts the previous consolidating JPanel in the CENTER position and a JButton in the AFTER_LAST_LINE position.

You can create a complex GUI by nesting JPanels with simpler Swing layouts.

The JFrame has a default BorderLayout. I put the drawing JPanel in the CENTER position and the additional consolidating JPanel in the AFTER_LAST_LINE position.

Controller

The controller is the ActionListener triggered by the JButton. I pass an instance of the GUI class and an instance of the model class to the controller class. The actionPerformed method gets the values from the two entry JPanels, adds the center point and radius to the two circles, and has the GUI repaint the drawing JPanel.

Edited to Add 1

The OP's comment leaves out a lot of information. Here's the class I created to create one instance of the entry JPanel. You have to create two instances of this class for the two entry JPanels.

public class CircleEntryPanel {
    
    private JPanel panel;
    
    private JTextField centerxField;
    private JTextField centeryField;
    private JTextField radiusField;
    
    public CircleEntryPanel(String title) {
        this.panel = createCircleEntryPanel(title);
    }

    private JPanel createCircleEntryPanel(String title) {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
        
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.LINE_START;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 5, 5, 5);
        gbc.gridwidth = 2;
        gbc.gridx = 0;
        gbc.gridy = 0;
        
        JLabel titleLabel = new JLabel(title);
        panel.add(titleLabel, gbc);
        
        gbc.gridwidth = 1;
        gbc.gridy++;
        JLabel centerxLabel = new JLabel("Center x:");
        panel.add(centerxLabel, gbc);
        
        gbc.gridx++;
        centerxField = new JTextField(4);
        centerxField.setHorizontalAlignment(JTextField.TRAILING);
        panel.add(centerxField, gbc);
        
        gbc.gridx = 0;
        gbc.gridy++;
        JLabel centeryLabel = new JLabel("Center y:");
        panel.add(centeryLabel, gbc);
        
        gbc.gridx++;
        centeryField = new JTextField(4);
        centeryField.setHorizontalAlignment(JTextField.TRAILING);
        panel.add(centeryField, gbc);
        
        gbc.gridx = 0;
        gbc.gridy++;
        JLabel radiusLabel = new JLabel("Radius:");
        panel.add(radiusLabel, gbc);
        
        gbc.gridx++;
        radiusField = new JTextField(4);
        radiusField.setHorizontalAlignment(JTextField.TRAILING);
        panel.add(radiusField, gbc);
        
        return panel;
    }

    public JPanel getPanel() {
        return panel;
    }

    public JTextField getCenterxField() {
        return centerxField;
    }

    public JTextField getCenteryField() {
        return centeryField;
    }

    public JTextField getRadiusField() {
        return radiusField;
    }

}

Edited to Add 2

Enough time has passed for me to post the complete runnable code for this project. I made all the additional classes inner classes so I can post the code as one block.

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class IntersectingCirclesGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new IntersectingCirclesGUI());
    }
    
    private IntersectingCirclesModel model;
    
    private CircleEntryPanel[] entryPanels;
    
    private DrawingPanel drawingPanel;
    
    public IntersectingCirclesGUI() {
        this.model = new IntersectingCirclesModel();
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Project");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        this.drawingPanel = new DrawingPanel(model);
        frame.add(drawingPanel, BorderLayout.CENTER);
        frame.add(createMainPanel(), BorderLayout.AFTER_LAST_LINE);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createMainPanel() {
        JPanel panel = new JPanel(new BorderLayout(5, 5));
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        panel.add(createEntryPanel(), BorderLayout.CENTER);
        
        JButton button = new JButton("Redraw Circles");
        button.addActionListener(new CircleListener(this, model));
        panel.add(button, BorderLayout.AFTER_LAST_LINE);
        
        return panel;
    }
    
    private JPanel createEntryPanel() {
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 5));
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        entryPanels = new CircleEntryPanel[2];
        entryPanels[0] = new CircleEntryPanel("Enter Circle 1 info:");
        entryPanels[1] = new CircleEntryPanel("Enter Circle 2 info:");
        
        panel.add(entryPanels[0].getPanel());
        panel.add(entryPanels[1].getPanel());
        
        return panel;
    }
    
    public void repaint() {
        drawingPanel.repaint();
    }
    
    public CircleEntryPanel[] getEntryPanels() {
        return entryPanels;
    }

    public class CircleEntryPanel {
        
        private JPanel panel;
        
        private JTextField centerxField;
        private JTextField centeryField;
        private JTextField radiusField;
        
        public CircleEntryPanel(String title) {
            this.panel = createCircleEntryPanel(title);
        }
    
        private JPanel createCircleEntryPanel(String title) {
            JPanel panel = new JPanel(new GridBagLayout());
            panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
            
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.anchor = GridBagConstraints.LINE_START;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.insets = new Insets(5, 5, 5, 5);
            gbc.gridwidth = 2;
            gbc.gridx = 0;
            gbc.gridy = 0;
            
            JLabel titleLabel = new JLabel(title);
            panel.add(titleLabel, gbc);
            
            gbc.gridwidth = 1;
            gbc.gridy++;
            JLabel centerxLabel = new JLabel("Center x:");
            panel.add(centerxLabel, gbc);
            
            gbc.gridx++;
            centerxField = new JTextField(4);
            centerxField.setHorizontalAlignment(JTextField.TRAILING);
            panel.add(centerxField, gbc);
            
            gbc.gridx = 0;
            gbc.gridy++;
            JLabel centeryLabel = new JLabel("Center y:");
            panel.add(centeryLabel, gbc);
            
            gbc.gridx++;
            centeryField = new JTextField(4);
            centeryField.setHorizontalAlignment(JTextField.TRAILING);
            panel.add(centeryField, gbc);
            
            gbc.gridx = 0;
            gbc.gridy++;
            JLabel radiusLabel = new JLabel("Radius:");
            panel.add(radiusLabel, gbc);
            
            gbc.gridx++;
            radiusField = new JTextField(4);
            radiusField.setHorizontalAlignment(JTextField.TRAILING);
            panel.add(radiusField, gbc);
            
            return panel;
        }

        public JPanel getPanel() {
            return panel;
        }

        public JTextField getCenterxField() {
            return centerxField;
        }

        public JTextField getCenteryField() {
            return centeryField;
        }

        public JTextField getRadiusField() {
            return radiusField;
        }
    
    }
    
    public class DrawingPanel extends JPanel {
        
        private static final long serialVersionUID = 1L;
        
        private IntersectingCirclesModel model;
        
        public DrawingPanel(IntersectingCirclesModel model) {
            this.model = model;
            this.setBackground(Color.WHITE);
            this.setPreferredSize(new Dimension(400, 200));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            
            Graphics2D g2d = (Graphics2D) g;
            g2d.setColor(Color.BLACK);
            g2d.setStroke(new BasicStroke(3f));
            
            boolean circlesDrawn = false;
            Circle[] circles = model.getCircles();
            for (int i = 0; i < circles.length; i++) {
                if (circles[i] != null) {
                    paintCircle(g2d, circles[i]);
                    circlesDrawn = true;
                }
            }
            
            if (circlesDrawn) {
                String text = (model.isIntersects()) ? "Yes" : "No";
                text = "Two Circles Intersect? " + text;
                Font font = getFont();
                FontRenderContext frc =
                        new FontRenderContext(null, true, true);

                Rectangle2D r2D = font.getStringBounds(text, frc);
                int rWidth = (int) Math.round(getWidth());
                int textWidth = (int) Math.round(r2D.getWidth());
                int textHeight = (int) Math.round(r2D.getHeight());

                int a = (rWidth - textWidth) / 2;
                int b = textHeight + 5;

                g2d.drawString(text, a, b);
            }
        }

        private void paintCircle(Graphics2D g2d, Circle circle) {
            int radius = circle.getRadius();
            int diameter = radius + radius;
            Point point = circle.getCenter();
            g2d.drawOval(point.x - radius, point.y - radius, 
                    diameter, diameter);
        }
    }
    
    public class CircleListener implements ActionListener {
        
        private IntersectingCirclesGUI frame;
        
        private IntersectingCirclesModel model;

        public CircleListener(IntersectingCirclesGUI frame, 
                IntersectingCirclesModel model) {
            this.frame = frame;
            this.model = model;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            CircleEntryPanel[] entryPanels = frame.getEntryPanels();
            Circle[] circles = model.getCircles();
            for (int i = 0; i < entryPanels.length; i++) {
                circles[i] = createCircle(entryPanels[i]);
            }
            frame.repaint();
        }
        
        private Circle createCircle(CircleEntryPanel panel) {
            int x = valueOf(panel.getCenterxField().getText().trim());
            int y = valueOf(panel.getCenteryField().getText().trim());
            int radius = valueOf(panel.getRadiusField().getText().trim());
            
            Circle circle = new Circle();
            circle.setCenter(x, y);
            circle.setRadius(radius);
            
            return circle;
        }
        
        private int valueOf(String number) {
            try {
                return Integer.valueOf(number);
            } catch (NumberFormatException e) {
                return -1;
            }
        }
        
    }
    
    public class IntersectingCirclesModel {
        
        private Circle[] circles;
        
        public IntersectingCirclesModel() {
            this.circles = new Circle[2];
        }

        public boolean isIntersects() {
            double distanceX = Math.abs(circles[0].getCenter().getX() - 
                    circles[1].getCenter().getX()); 
            double distanceY = Math.abs(circles[0].getCenter().getY() - 
                    circles[1].getCenter().getY()); 
            double distance1 = (distanceX * distanceX + distanceY * distanceY);
            
            double radius1 = circles[0].getRadius();
            double radius2 = circles[1].getRadius();
            double diameter = radius1 + radius2;
            double distance2 = diameter * diameter;
            
            System.out.println(distance1 + " " + distance2);
            return distance1 <= distance2;
        }

        public Circle[] getCircles() {
            return circles;
        }
        
        public void setCircle(Circle circle, int index) {
            this.circles[index] = circle;
        }
    }
    
    public class Circle {
        
        private int radius;
        
        private Point center;

        public int getRadius() {
            return radius;
        }

        public void setRadius(int radius) {
            this.radius = radius;
        }

        public Point getCenter() {
            return center;
        }

        public void setCenter(Point center) {
            this.center = center;
        }
        
        public void setCenter(int x, int y) {
            this.center = new Point(x, y);
        }
        
    }

}

Upvotes: 1

c0der
c0der

Reputation: 18792

Avoid using static fields. Instead use setters in Circles:

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

public class Circle extends JFrame implements ActionListener{

    private final JPanel p1,p2,p3,buttonsize;
    private final JLabel title,lb1,lb2,lb3,lb4,lb5,lb6,lb7,lb8,lb9,lb10;
    private final JTextField circle1x,circle1y,circle1r,circle2x,circle2y,circle2r;
    private final JButton drawButton;
    private final Circles circles;

    public static void main(String[]args)
    {
        Circle c = new Circle();
        c.setSize(400,400);
        c.setTitle("Project");
        c.setVisible(true);
        c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public Circle() {

        title = new JLabel("Two circles intersect? No");
        p1 = new JPanel();
        p1.add(title);

        p2 = new JPanel();

        lb1 = new JLabel("Enter circle 1");
        lb2 = new JLabel("Enter circle 2");
        lb3 = new JLabel("info:");
        lb4 = new JLabel("info:");
        lb5 = new JLabel("Center x:");
        lb6 = new JLabel("Center y:");
        lb7 = new JLabel("Radius:");
        lb8 = new JLabel("Center x:");
        lb9 = new JLabel("Center y:");
        lb10 = new JLabel("Radius:");

        circle1x = new JTextField(1);
        circle1y = new JTextField(1);
        circle1r = new JTextField(1);
        circle2x = new JTextField(1);
        circle2y = new JTextField(1);
        circle2r = new JTextField(1);
        drawButton = new JButton("Redraw Circles");
        buttonsize = new JPanel();
        buttonsize.setSize(50,50);
        buttonsize.add(drawButton);
        p3 = new JPanel();
        p3.setLayout(new GridLayout(5,5));

        p3.add(lb1);p3.add(lb3);p3.add(new JLabel(""));p3.add(lb2);p3.add(lb4);
        p3.add(lb5);p3.add(circle1x);p3.add(new JLabel(""));p3.add(lb8);p3.add(circle2x);
        p3.add(lb6);p3.add(circle1y);p3.add(new JLabel(""));p3.add(lb9);p3.add(circle2y);
        p3.add(lb7);p3.add(circle1r);p3.add(new JLabel(""));p3.add(lb10);p3.add(circle2r);
        p3.add(new JLabel(""));p3.add(new JLabel(""));p3.add(drawButton);p3.add(new JLabel(""));p3.add(new JLabel(""));

        setLayout(new BorderLayout());  //BorderLayout is the default for JFrame
        //call the constructor of the panel
        add(p1,BorderLayout.NORTH);
        circles = new Circles();
        add(circles,BorderLayout.CENTER);
        add(p3,BorderLayout.SOUTH);

        drawButton.addActionListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent e)   {

        if(e.getSource()!= drawButton)  return;
        
        double c1x = Double.parseDouble(circle1x.getText());
        double c1y = Double.parseDouble(circle1y.getText());
        double c1r = Double.parseDouble(circle1r.getText());
        double c2x = Double.parseDouble(circle2x.getText());
        double c2y = Double.parseDouble(circle2y.getText());
        double c2r = Double.parseDouble(circle2r.getText());

        circles.setX1((int) c1x);
        circles.setX2((int) c2x);
        circles.setY1((int) c1y);
        circles.setY2((int) c2y);
        circles.setR1((int) c1r);
        circles.setR2((int) c2r);
        repaint();
    }
}

class Circles extends JPanel{

    private int x1=30,x2=200,y1=10,y2=10,r1=10,r2=10;

    @Override
    public void paintComponent(Graphics g)  {
        super.paintComponent(g);
        g.setColor(Color.BLACK);
        g.drawOval(x1, y1, r1, r1);
        g.drawOval(x2, y2, r2, r2);
    }

    public void setX1(int x1) {
        this.x1 = x1;
    }

    public void setX2(int x2) {
        this.x2 = x2;
    }

    public void setY1(int y1) {
        this.y1 = y1;
    }

    public void setY2(int y2) {
        this.y2 = y2;
    }

    public void setR1(int r1) {
        this.r1 = r1;
    }

    public void setR2(int r2) {
        this.r2 = r2;
    }
}

Upvotes: 1

Related Questions