Search code examples
javaswingshapespaintcomponentmenubar

how to change shapes when clicking menu items in java


I am having a problem changing the shapes displayed when the user clicks on the menu item in java using the JFrame. Can anyone suggest how I can solve this? Below is my code:

public class PlayingWithShapes implements ActionListener
{
    protected JMenuItem circle = new JMenuItem("Circle");
    protected String identifier = "circle";
    public PlayingWithShapes()
    {
    JMenuBar menuBar = new JMenuBar();
    JMenu shapes = new JMenu("Shapes");
    JMenu colors = new JMenu("Colors");

    circle.addActionListener(this);
    shapes.add(circle);
    menuBar.add(shapes);
    menuBar.add(colors);
    JFrame frame = new JFrame("Playing With Shapes");
    frame.setSize(600,400);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
    frame.add(new Shapes());
    frame.setJMenuBar(menuBar);
}

public static void main(String args[])
{
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
           new PlayingWithShapes();
        }
    };
    EventQueue.invokeLater(runnable);

}

I want to change the shape as circle when clicking on the circle menuItem

@Override
public void actionPerformed(ActionEvent click) {

   if(click.getSource() == circle){
      Shapes shape = new Shapes();

   }
}

public class Shapes extends JPanel
{

How can I then call rectangle?

    @Override
    public void paintComponent(Graphics shapes)
    {
        circle(shapes);
    }

    public void circle(Graphics shapes)
    {
        shapes.setColor(Color.yellow);
        shapes.fillOval(200,100, 100, 100);
    }
    public void rectangle(Graphics shapes)
    {
        shapes.setColor(Color.MAGENTA);
        shapes.fillRect(200,100,100,100);
    }

}

}

Any help is much appreciated.


Solution

  • Suggestions:

    • Don't create a new Shapes JPanel within your actionPerformed as this achieves nothing.
    • Instead within actionPerformed change the state of a field of the class, and base the drawing within your paintComponent method on the state held by that field.
    • For instance, if you only have two different types of shapes, the above field could simply be a boolean, perhaps called drawRectangle, and in actionPerformed you'd change this to true or false and call repaint();. And then in you'd use an if block within paintComponent drawing a Rectangle if it is true or a oval if not.
    • If you want to have the ability to draw multiple different shapes, create an enum and make the field discussed above a field of this enum type. Then use a switch statement within paintComponent to decide which shape to draw.
    • If you want to show different shapes at the same time, then you'll need to create a collection of Shape such as an ArrayList<Shape> and add Shape-derived objects to this collection, and then iterate through it in a for loop within paintComponent using a Graphics2D object to draw each Shape. I don't think that you need this right now.
    • Don't forget to call the super.paintComponent(g); within your method override.

    i.e.,

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (drawRectangle) {
            rectangle(g);
        } else {
            circle(g);
        }
    }