0

I am trying to draw a circle with the press of a button in java. I put the System.out.println() inside the action method to make sure my code was working. The println shows up but no circle drawing anywhere. Any Suggestions? Thank you

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;


public class CircleViewer {


    public static void main(String[] args)
    {
        CircleComponent circle = new CircleComponent();


              JButton button = new JButton("Draw");
              final JPanel panel = new JPanel();
              panel.add(button);
              JFrame frame = new JFrame();

                  class addActionListener implements ActionListener
                  {
                     public void actionPerformed(ActionEvent event)
                     {
                         CircleComponent component = new CircleComponent();
                         String x = JOptionPane.showInputDialog("X Coordinate", "Enter an x coordinate");
                         int xCoord = Integer.parseInt(x);
                         String y = JOptionPane.showInputDialog("Y Coordinate", "Enter a y coordinate");
                         int yCoord = Integer.parseInt(y);
                         String width = JOptionPane.showInputDialog("Radius", "Enter the length of the radius");
                         int radius = Integer.parseInt(width);
                         component.setLocation(xCoord,yCoord);
                         component.getWidth(radius);
                         panel.add(component);
                         System.out.println("CLICKED!");

                     }          
                  }

                  frame.add(panel);
                  ActionListener action = new addActionListener();
                  button.addActionListener(action);

                  frame.setSize(500, 500);
                  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  frame.setVisible(true); 
          }

    }



import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.JOptionPane;

/**
   This component lets the user draw a circle by clicking
   a button.
*/
public class CircleComponent extends JPanel 
{ 
       private int x;
       private int y;
       private int width;
       Ellipse2D.Double circle;

       public CircleComponent()
       {
           circle = new Ellipse2D.Double(x, y, width, width);
       }

       public Dimension getPreferredSize() 
       {
           return new Dimension(500,500);
       }

       public void paintComponent(Graphics g)
       {  
           super.paintComponent(g);
           Graphics2D g2 = (Graphics2D) g;
           g2.draw(circle);

       } 

       public int getWidth(int aWidth)
       {
            width = aWidth;
            return width;
       }

} 
tblizzard
  • 3
  • 1
  • 2
  • 5

1 Answers1

3

You need to override the getPreferredSize() method of you custom component. By default the size is (0, 0) so there is nothing to paint.

The revalidate() should be done on the panel, not the component.

Your getX() and getY() methods make no sense. If you want to position the component on the panel you should be using the setLocation(...) method of the component.

Edit:

There are still lots of probolems. I'll try to explain them and then give a better (still not a great) example of how you might do this.

circle = new Ellipse2D.Double(x, y, width, width);
  1. When you create the circle shape all the parameters have a value of 0 so there is nothing to paint. You can't just change the values of the variables x, y and width later and expect the circle to reflect those values.

  2. The size of the component is wrong. You can't just make an arbitrary size of 500 x 500. The preferred size should be the size of the circle.

  3. You can't just add the component to the panel because the panel uses a FlowLayout by default. This means the setLocation() method will be ignored. I changed your code to use a null layout. This means that the location you specify will now be used and you must also specify the size of the component.

  4. I changed your code to use an "anonymous inner class" for the ActonListener. This is more common then defining a class in the middle of another class.

Here is the quick example:

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

public class CircleComponent extends JPanel
{
       Ellipse2D.Double circle;

       public CircleComponent(int radius)
       {
           circle = new Ellipse2D.Double(0, 0, radius, radius);
           setOpaque(false);
       }

       public Dimension getPreferredSize()
       {
            Rectangle bounds = circle.getBounds();
           return new Dimension(bounds.width, bounds.height);
       }

       public void paintComponent(Graphics g)
       {
           super.paintComponent(g);
           Graphics2D g2 = (Graphics2D) g;
           g2.setColor( getForeground() );
           g2.fill(circle);

       }
/*
       public int getWidth(int aWidth)
       {
            width = aWidth;
            return width;
       }
*/

    public static void main(String[] args)
    {
            //  Create a panel using a null layout so we can add components at random positions
            final JPanel center = new JPanel();
            center.setLayout(null);

              JButton button = new JButton("Draw");
              button.addActionListener( new ActionListener()
              {
                 public void actionPerformed(ActionEvent event)
                 {
                     String x = JOptionPane.showInputDialog("X Coordinate", "Enter an x coordinate");
                     int xCoord = Integer.parseInt(x);
                     String y = JOptionPane.showInputDialog("Y Coordinate", "Enter a y coordinate");
                     int yCoord = Integer.parseInt(y);
                     String width = JOptionPane.showInputDialog("Radius", "Enter the length of the radius");
                     int radius = Integer.parseInt(width);
                     CircleComponent component = new CircleComponent(radius);
                     component.setLocation(xCoord,yCoord);
                     component.setSize(component.getPreferredSize());
                     center.add(component);
                     center.repaint();

                 }
              });

              JFrame frame = new JFrame();
              frame.add(center, BorderLayout.CENTER);
              frame.add(button, BorderLayout.NORTH);
              frame.setSize(500, 500);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.setVisible(true);
    }
}
camickr
  • 321,443
  • 19
  • 166
  • 288
  • I want the user to be able to pick where they want to put the circle though does that matter? I also am not understanding what you mean by needing to override the getPreferredSize() method. Sorry I am kind of new to all this. – tblizzard Oct 14 '13 at 19:26
  • `I want the user to be able to pick where they want to put the circle` that is why you use the `setLocation(...)` method using the values entered by the user. The preferred size of your component is the size of the circle. So you need to override the getPreferredSize() method of your component to return a Dimension object with the proper size. Read the section from the Swing tutorial on [Custom Painting](http://docs.oracle.com/javase/tutorial/uiswing/painting/step2.html) for a simple example that does this. – camickr Oct 14 '13 at 19:33
  • I read over the tutorial and added the getPreferredSize() method to my code. Can you edit my code and try to see if you can get it to run because my output is still blank. – tblizzard Oct 14 '13 at 19:57
  • Well I suggest that you start with the tutorial example and then make changes to that code. The tutorial shows you a better way to structure your code. It shows you how to create components on the Event Dispatch Thread. It shows you how to create a frame and add a component to the frame. The creation of the frame should not be part of your CircleComponent class. Once you have restruted the code then if you still have problems you can repost the code – camickr Oct 14 '13 at 20:09
  • I restructured my classes and a circle is drawn but only if I replace numbers for x,y,and width...circle = new Ellipse2D.Double(x, y, width, width); I think there is something wrong when I pass the inputs with JOption? – tblizzard Oct 14 '13 at 22:45
  • Thank you very much camickr for your help my program is running just as i need it too! – tblizzard Oct 15 '13 at 22:58