Search code examples
javaswingcolorsawtpaintcomponent

how to change shape and colors when clicking menuitems in java


Im having trouble changing the colors of a certain shape. But when user click on a menuitem, it will successfully change into another shape. Now the problem is I cannot think of a solution that will solve this one. Can anyone help me on this? Help are much appreciated. Thank you.

    @Override
    public void paintComponent(Graphics shapes)
    {
        super.paintComponent(shapes);
        switch(colorNo)
        {
            case 0 : color = Color.RED;break;
            case 1 : color = Color.BLUE;break;
            case 2 : color = Color.MAGENTA;break;
        }
        switch(numbers)
        {
            case 0 : circle(shapes);break;
            case 1 : rectangle(shapes);break;
            case 2 : square(shapes);break;
            case 3 : triangle(shapes);break;
        }  
    }

    public void circle(Graphics shapes)
    {
        shapes.setColor(color);
        shapes.fillOval(250,100, 100, 100);
    }


    @Override
    public void actionPerformed(ActionEvent click) {
        if(click.getSource() == circle){
            numbers = 0;
            repaint();
        }else if(click.getSource() == square){
            numbers = 1; repaint();
        }else if(click.getSource() == rectangle){
            numbers = 2; repaint();
        }else if(click.getSource() == triangle){
            numbers = 3; repaint();
        }
        if(click.getSource() == red){
            colorNo = 0; repaint();
        }

    }

Solution

  • Simple -- in your paintComponent method, after your super's paintComponent call, and before your switch statement where you set the shape, set the Graphics object's Color, in the same way that you set the shape. You'll of course have to add a listener to each of your color menu items for this to work.

    It's much easier and cleaner if you use AbstractActions instead of having everything share the same ActionListener. For example, this code doesn't do exactly what you're trying to do, but it can give you some ideas.

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    
    import javax.swing.*;
    
    
    public class MyShapes extends JPanel {
        private static final int PREF_W = 400;
        private static final int PREF_H = PREF_W;
        private JMenuBar menuBar = new JMenuBar();
        private Color color = Color.WHITE;
    
        public MyShapes() {
            JMenu colorMenu = new JMenu("Color");
            colorMenu.add(new JMenuItem(new ColorAction("Black", Color.BLACK)));
            colorMenu.add(new JMenuItem(new ColorAction("White", Color.WHITE)));
            colorMenu.add(new JMenuItem(new ColorAction("Red", Color.RED)));
            colorMenu.add(new JMenuItem(new ColorAction("Blue", Color.BLUE)));
            colorMenu.add(new JMenuItem(new ColorAction("Green", Color.GREEN)));
            menuBar.add(colorMenu);
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(color);
            g.fillRect(0, 0, getWidth(), getHeight());
        }
    
        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet()) {
                return super.getPreferredSize();
            }
            return new Dimension(PREF_W, PREF_H);
        }
    
        public JMenuBar getMenuBar() {
            return menuBar;
        }
    
        private class ColorAction extends AbstractAction {
            private Color actionColor;
    
            public ColorAction(String name, Color color) {
                super(name);
                this.actionColor = color;
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                color = actionColor;
                repaint();
            }
        }
    
        private static void createAndShowGui() {
            MyShapes mainPanel = new MyShapes();
    
            JFrame frame = new JFrame("MyShapes");
            frame.setJMenuBar(mainPanel.getMenuBar());
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGui();
                }
            });
        }
    }
    

    Note that you could draw your shapes in the same way -- by filling a variable from within the menu item's action's actionPerformed method. Only this time the variable that is of the DrawShape interface type and will use it for its method, here the public void draw(Graphics g). This type of program design pattern is called the Command Pattern. For example:

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Polygon;
    import java.awt.RenderingHints;
    import java.awt.event.ActionEvent;
    
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class MyShapes extends JPanel {
        private static final int PREF_W = 400;
        private static final int PREF_H = PREF_W;
        private JMenuBar menuBar = new JMenuBar();
        private Color color = null;
        public DrawShape drawShape = null;
    
        public MyShapes() {
            // create and fill colorMenu
            JMenu colorMenu = new JMenu("Color");
            colorMenu.add(new JMenuItem(new ColorAction("Black", Color.BLACK)));
            colorMenu.add(new JMenuItem(new ColorAction("White", Color.WHITE)));
            colorMenu.add(new JMenuItem(new ColorAction("Red", Color.RED)));
            colorMenu.add(new JMenuItem(new ColorAction("Blue", Color.BLUE)));
            colorMenu.add(new JMenuItem(new ColorAction("Green", Color.GREEN)));
    
            // create and fill shapeMenu
            JMenu shapeMenu = new JMenu("Shape");
            shapeMenu.add(new JMenuItem(new DrawShapeAction("Square", new DrawShape() {
    
                @Override
                public void draw(Graphics g) {
                    int x = getWidth() / 4;
                    int y = getHeight() / 4;
                    int width = getWidth() / 2;
                    int height = getHeight() / 2;
                    g.fillRect(x, y, width, height);
                }
            })));
            shapeMenu.add(new JMenuItem(new DrawShapeAction("Circle", new DrawShape() {
    
                @Override
                public void draw(Graphics g) {
                    int x = getWidth() / 4;
                    int y = getHeight() / 4;
                    int width = getWidth() / 2;
                    int height = getHeight() / 2;
                    g.fillOval(x, y, width, height);
                }
            })));
            shapeMenu.add(new JMenuItem(new DrawShapeAction("Triangle", new DrawShape() {
    
                @Override
                public void draw(Graphics g) {
                    int[] x = new int[3];
                    int[] y = new int[3];
                    x[0] = getWidth() / 4;
                    x[1] = getWidth() / 2;
                    x[2] = 3 * getWidth() / 4;
                    y[0] = 3 * getHeight() / 4;
                    y[1] = getHeight() / 4;
                    y[2] = y[0];
                    Polygon polygon = new Polygon(x, y, 3);
                    g.fillPolygon(polygon);
                }
            })));
    
            // add both JMenus to the JMenuBar
            menuBar.add(colorMenu);
            menuBar.add(shapeMenu);
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
    
            // if either color or drawShape are not set, exit this method and draw nothing
            if (color == null || drawShape == null) {
                return;
            }
    
            // to smooth out the edges
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
            // set color and call drawShape's draw method
            g.setColor(color);
            drawShape.draw(g);
        }
    
        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet()) {
                return super.getPreferredSize();
            }
            return new Dimension(PREF_W, PREF_H);
        }
    
        public JMenuBar getMenuBar() {
            return menuBar;
        }
    
        private class ColorAction extends AbstractAction {
            private Color actionColor;
    
            public ColorAction(String name, Color color) {
                super(name);
                this.actionColor = color;
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                MyShapes.this.color = actionColor;
                repaint();
            }
        }
    
        private class DrawShapeAction extends AbstractAction {
            private DrawShape actionDrawShape;
    
            public DrawShapeAction(String name, DrawShape drawShape) {
                super(name);
                this.actionDrawShape = drawShape;
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                MyShapes.this.drawShape = actionDrawShape;
                repaint();
            }
        }
    
        private interface DrawShape {
            void draw(Graphics g);
        }
    
        private static void createAndShowGui() {
            MyShapes mainPanel = new MyShapes();
    
            JFrame frame = new JFrame("MyShapes");
            frame.setJMenuBar(mainPanel.getMenuBar());
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGui();
                }
            });
        }
    }