Reputation: 11
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
Reputation: 51445
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.
Here's another example.
And another.
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:
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.
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.
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
.
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;
}
}
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
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