Why is the ActionListener not working with the buttons in Java GUI?

I’m working on a Java GUI application, and I’m having trouble getting the ActionListener to work properly with my buttons. When I click on the buttons, nothing happens, and the corresponding methods in my class are not being executed. I’m not sure what I’m doing wrong. Here are the concerned classes (particularly "Draw" and "DrawGUI") of my code:

`package mydraw.logic;

import static mydraw.gui.DrawGUI.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import mydraw.gui.DrawGUI;

/**
The Draw class provides high-level API methods for drawing shapes using the DrawGUI.
It contains methods for drawing rectangles, ovals, and polylines, as well as a test method
for automatically drawing a set of shapes.
It also provides a constructor to create an instance of the DrawGUI and a method to get the
DrawGUI window component.
*/

/** The application class. Processes high-level commands sent by GUI */
public class Draw {
    private static final Object QUIT = null;
    private static final Object CLEAR = null;
    private static final Object SAVE = null;
    private static final Object AUTODRAW = "autoDraw";
    public Graphics g;
    protected DrawGUI window;

    /** main entry point. Just create an instance of this application class */
    public static void main(String[] args) {
        new Draw();
    }

    /** Application constructor: create an instance of our GUI class */
    public Draw() {
        window = new DrawGUI(this);
        g = window.getGraphics();
    }

    /**
     * This is the application method that processes commands sent by the GUI.
     * 
     * @param command - command sent by the GUI.
     */
    public void doCommand(String command) {
        if (command.equals(CLEAR)) {
            window.clear();
            System.out.println("CLEAR button clicked");
        } else if (command.equals(QUIT)) {
            window.dispose();
            System.out.println("QUIT button clicked");
            System.exit(0);
        } else if (command.equals(SAVE)) {
            Image img = window.createImageFromPanel();
            try {
                writeImage(img, "hallo.bmp");
                System.out.println("SAVE button clicked");
            } catch (IOException e) {
                System.err.println("Not working");
            }
        } else if (command.equals(AUTODRAW)) {
            autoDraw();
            System.out.println("AUTODRAW button clicked");
        }
    }

    /**
     * API method: get height.
     * 
     * @return height of the window.
     */
    public int getHeight() {
        return window.getContentPane().getHeight();
    }

    /**
     * API method: set height.
     * 
     * @param height - the new height of the window.
     * @throws SizeException if the input is negative.
     */
    public void setHeight(int height) throws SizeException {
        if (height < 0) {
            throw new SizeException("Höhe muss positiv sein.");
        }
        Dimension d = window.getContentPane().getPreferredSize();
        d.height = height;
        window.getContentPane().setPreferredSize(d);
        window.pack();
    }

    /**
     * API method: get width.
     * 
     * @return width of the window.
     */
    public int getWidth() {
        return window.getContentPane().getWidth();
    }

    /**
     * API method: set width.
     * 
     * @param width - the new width of the window.
     * @throws SizeException if the input is negative.
     */
    public void setWidth(int width) throws SizeException {
        if (width < 0) {
            throw new SizeException("Breite muss positiv sein.");
        }
        Dimension d = window.getContentPane().getPreferredSize();
        d.width = width;
        window.getContentPane().setPreferredSize(d);
        window.pack();
    }

    /**
     * API method: set foreground color.
     * 
     * @param new_color - new foreground color.
     * @throws ColorException if the input is not a valid color.
     */
    public void setFGColor(String new_color) throws ColorException {
        Color color = Color.getColor(new_color);
        if (color == null) {
            throw new ColorException("Ungueltiger Farbname.");
        }
        window.setForeground(color);
    }

    /**
     * API method: get foreground color.
     * 
     * @return the current foreground color.
     */
    public String getFGColor() {
        return window.getForeground().toString();
    }

    /**
     * API method: set background color.
     * 
     * @param new_color - new background color.
     * @throws ColorException if the input is not a valid color.
     */
    public void setBGColor(String new_color) throws ColorException {
        Color color = Color.getColor(new_color);
        if (color == null) {
            throw new ColorException("Ungueltiger Farbname.");
        }
        window.setBackground(color);
    }

    /**
     * API method: get background color.
     * 
     * @return the current background color.
     */
    public String getBGColor() {
        return window.getBackground().toString();
    }

    /**
     * API method: get drawing.
     * 
     * @return the drawing as a BufferedImage.
     */
    public BufferedImage getDrawing() {
        int width = window.getContentPane().getWidth();
        int height = window.getContentPane().getHeight();

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

        Graphics2D g2d = image.createGraphics();
        window.paintComponents(g2d);
        g2d.dispose();
        return image;
    }

    /**
     * API method: write image.
     * 
     * @param img      - the image to be saved.
     * @param filename - the filename to save the image to.
     * @throws IOException if there is an error while writing the image.
     */
    public void writeImage(Image img, String filename) throws IOException {
        MyBMPFile.write(filename, img);
    }

    /**
     * API method: read image.
     * 
     * @param filename - the filename to read the image from.
     * @return the image as an Image object.
     * @throws IOException if there is an error while reading the image.
     */
    public Image readImage(String filename) throws IOException {
        return MyBMPFile.read(filename);
    }

    /**
     * API method: clear the window.
     */
    public void clear() {
        g.setColor(window.getBackground());
        g.fillRect(0, 0, window.getContentPane().getWidth(), window.getContentPane().getHeight());
    }

    /**
     * 
     * Test method to automatically draw a set of shapes using the DrawGUI.
     * 
     * Draws a rectangle, an oval, and a polyline.
     */
    public void autoDraw() {

        g.setColor(Color.RED);
        drawRectangle(new Point(50, 100), new Point(150, 200)); // Rectangle 1
        g.setColor(Color.BLUE);
        drawRectangle(new Point(160, 100), new Point(260, 200)); // Rectangle 2
        g.setColor(Color.GREEN);
        drawRectangle(new Point(270, 100), new Point(370, 200)); // Rectangle 3
        g.setColor(Color.BLACK);
        drawRectangle(new Point(380, 100), new Point(480, 200)); // Rectangle 4

        g.setColor(Color.RED);
        drawOval(new Point(50, 250), new Point(150, 350)); // Oval 1
        g.setColor(Color.BLUE);
        drawOval(new Point(175, 250), new Point(275, 350)); // Oval 2
        g.setColor(Color.GREEN);
        drawOval(new Point(300, 250), new Point(400, 350)); // Oval 3
        g.setColor(Color.BLACK);
        drawOval(new Point(425, 250), new Point(525, 350)); // Oval 4

        g.setColor(Color.RED);
        java.util.List<Point> points1 = new ArrayList<>(Arrays.asList(new Point(90, 180), new Point(100, 150),
                new Point(110, 180), new Point(120, 150), new Point(130, 180)));
        drawPolyLine(points1); // Polyline 1

        g.setColor(Color.BLUE);
        java.util.List<Point> points2 = new ArrayList<>(Arrays.asList(new Point(190, 180), new Point(200, 150),
                new Point(210, 180), new Point(220, 150), new Point(230, 180)));
        drawPolyLine(points2); // Polyline 2

        g.setColor(Color.GREEN);
        java.util.List<Point> points3 = new ArrayList<>(Arrays.asList(new Point(290, 180), new Point(300, 150),
                new Point(310, 180), new Point(320, 150), new Point(330, 180)));
        drawPolyLine(points3); // Polyline 3

        g.setColor(Color.BLACK);
        java.util.List<Point> points4 = new ArrayList<>(Arrays.asList(new Point(390, 180), new Point(400, 150),
                new Point(410, 180), new Point(420, 150), new Point(430, 180)));
        drawPolyLine(points4); // Polyline 4
    }

    /**
     * 
     * Method to draw a rectangle on the DrawGUI.
     * 
     * @param upper_left  the upper-left corner of the rectangle
     * 
     * @param lower_right the lower-right corner of the rectangle
     */
    public void drawRectangle(Point upper_left, Point lower_right) {
        int width = lower_right.x - upper_left.x;
        int height = lower_right.y - upper_left.y;

        g.drawRect(upper_left.x, upper_left.y, width, height);
    }

    /**
     * 
     * Method to draw an oval on the DrawGUI.
     * 
     * @param upper_left  the upper-left corner of the oval
     * 
     * @param lower_right the lower-right corner of the oval
     */
    public void drawOval(Point upper_left, Point lower_right) {
        int width = lower_right.x - upper_left.x;
        int height = lower_right.y - upper_left.y;

        g.drawOval(upper_left.x, upper_left.y, width, height);
    }

    /**
     * 
     * Method to draw a polyline on the DrawGUI.
     * 
     * @param points a list of points defining the vertices of the polyline
     */
    public void drawPolyLine(java.util.List<Point> points) {
        int[] xpoints = new int[points.size()];
        int[] ypoints = new int[points.size()];
        for (int i = 0; i < points.size(); i++) {
            xpoints[i] = points.get(i).x;
            ypoints[i] = points.get(i).y;
        }

        g.drawPolyline(xpoints, ypoints, points.size());
    }

    /**
     * Helper method for the test class.
     *
     * @return window return the window
     */
    public Window getWindow() {
        return window;
    }

}`



`package mydraw.gui;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.*;

import javax.swing.*;

import mydraw.logic.Draw;

/** This class implements the GUI for our application */
public class DrawGUI extends JFrame {

    private static final long serialVersionUID = 1L;

    /**
     * The default width of the drawing window.
     */
    public static final int WIDTH = 800;

    /**
     * The default height of the drawing window.
     */
    public static final int HEIGHT_DEFAULT = 400;

    /**
     * The labels for the buttons.
     */
    public static final String SCRIBBLE = "Scribble";
    public static final String RECTANGLE = "Rectangle";
    public static final String OVAL = "Oval";
    public static final String BLACK = "Black";
    public static final String GREEN = "Green";
    public static final String RED = "Red";
    public static final String BLUE = "Blue";
    public static final String CLEAR = "Clear";
    public static final String QUIT = "Quit";
    public static final String SAVE = "Save";
    public static final String AUTODRAW = "autoDraw";

    private final Draw logic;
    private Color color;
    private final DrawingPanel drawingPanel;

    /**
     * Constructs a new DrawGUI object with the specified Draw logic.
     *
     * @param logic the Draw object to use for the GUI's logic
     */
    public DrawGUI(Draw logic) {
        super("Draw");
        this.logic = logic;
        color = Color.black;
        drawingPanel = new DrawingPanel();

        setSize(WIDTH, HEIGHT_DEFAULT);

        Choice shape_chooser = new Choice();
        shape_chooser.add(SCRIBBLE);
        shape_chooser.add(RECTANGLE);
        shape_chooser.add(OVAL);
        shape_chooser.addItemListener(new ShapeManager(this, drawingPanel));

        Choice color_chooser = new Choice();
        color_chooser.add(BLACK);
        color_chooser.add(GREEN);
        color_chooser.add(RED);
        color_chooser.add(BLUE);

        color_chooser.addItemListener(e -> {
            if (e.getItem().equals(BLACK)) {
                color = Color.black;
            } else if (e.getItem().equals(GREEN)) {
                color = Color.green;
            } else if (e.getItem().equals(RED)) {
                color = Color.red;
            } else if (e.getItem().equals(BLUE)) {
                color = Color.blue;
            }
        });

        JButton clear = new JButton(CLEAR);
        JButton quit = new JButton(QUIT);
        JButton save = new JButton(SAVE);
        JButton autodraw = new JButton(AUTODRAW);
        JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 5));
        clear.addActionListener(e -> logic.doCommand(CLEAR));
        quit.addActionListener(e -> logic.doCommand(QUIT));
        save.addActionListener(e -> logic.doCommand(SAVE));
        autodraw.addActionListener(e -> logic.doCommand(AUTODRAW));

        setLayout(new BorderLayout());
        topPanel.add(save);
        topPanel.add(autodraw);
        topPanel.add(new JLabel("Shape:"));
        topPanel.add(shape_chooser);
        topPanel.add(new JLabel("Color:"));
        topPanel.add(color_chooser);
        topPanel.add(clear);
        topPanel.add(quit);
        add(topPanel, BorderLayout.NORTH);
        add(drawingPanel, BorderLayout.CENTER);

        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                DrawGUI.this.logic.doCommand("quit");
            }

        });

        this.setBackground(Color.white);
        this.setVisible(true);

    }

    /**
     * Returns the currently selected drawing color.
     *
     * @return the currently selected drawing color
     */
    public Color getColor() {
        return color;
    }

    /**
     * Creates a new BufferedImage of the drawing panel.
     *
     * @return a new BufferedImage of the drawing panel
     */
    public BufferedImage createImageFromPanel() {
        int width = drawingPanel.getWidth();
        int height = drawingPanel.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = image.createGraphics();
        drawingPanel.paint(g2d);
        g2d.dispose();
        return image;
    }

    /**
     * Clears the drawing panel and resets the GUI.
     */
    public void clear() {
        Graphics g = getGraphics();
        g.setColor(getBackground());
        g.fillRect(0, 0, getSize().width, getSize().height);
        drawingPanel.clearImage();
    }

}`


`package mydraw.gui;

import java.awt.*;
import java.awt.event.*;

@SuppressWarnings("unused")
public class ShapeManager implements ItemListener {
    DrawGUI gui;
    final DrawingPanel drawingPanel;

    abstract class ShapeDrawer extends MouseAdapter implements MouseMotionListener {
        @Override
        public void mouseMoved(MouseEvent e) {
            /* ignore */ }
    }

    // if this class is active, the mouse is interpreted as a pen
    class ScribbleDrawer extends ShapeDrawer implements MouseMotionListener {
        int lastx, lasty;

        @Override
        public void mousePressed(MouseEvent e) {
            lastx = e.getX();
            lasty = e.getY();
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            Graphics2D g2d = drawingPanel.getImageGraphics();
            int x = e.getX() - drawingPanel.getX(), y = e.getY() - drawingPanel.getY();
            g2d.setColor(gui.getColor());
            g2d.setPaintMode();
            g2d.drawLine(lastx, lasty, x, y);
            g2d.dispose();
            lastx = x;
            lasty = y;
            drawingPanel.repaint(); // Neu hinzugefügt
        }
    }

    // if this class is active, rectangles are drawn
    class RectangleDrawer extends ShapeDrawer {
        int pressx, pressy;
        int lastx = -1, lasty = -1;

        // mouse pressed => fix first corner of rectangle
        @Override
        public void mousePressed(MouseEvent e) {
            pressx = e.getX();
            pressy = e.getY();
        }

        // mouse released => fix second corner of rectangle
        // and draw the resulting shape
        @Override
        public void mouseReleased(MouseEvent e) {
            Graphics2D g2d = drawingPanel.getImageGraphics();
            if (lastx != -1) {
                // first undraw a rubber rect
                g2d.setXORMode(gui.getColor());
                g2d.setColor(gui.getBackground());
                doDraw(pressx, pressy, lastx, lasty, g2d);
                lastx = -1;
                lasty = -1;
            }
            // these commands finish the rubberband mode
            g2d.setPaintMode();
            g2d.setColor(gui.getColor());
            // draw the final rectangle
            doDraw(pressx, pressy, e.getX(), e.getY(), g2d);
            g2d.dispose();
            drawingPanel.repaint(); // Neu hinzugefügt
        }

        // mouse released => temporarily set second corner of rectangle
        // draw the resulting shape in "rubber-band mode"
        @Override
        public void mouseDragged(MouseEvent e) {
            Graphics g = drawingPanel.getImageGraphics();
            // these commands set the rubberband mode
            g.setXORMode(gui.getColor());
            g.setColor(gui.getBackground());
            if (lastx != -1) {
                // first undraw previous rubber rect
                doDraw(pressx, pressy, lastx, lasty, g);

            }
            lastx = e.getX();
            lasty = e.getY();
            // draw new rubber rect
            doDraw(pressx, pressy, lastx, lasty, g);
        }

        public void doDraw(int x0, int y0, int x1, int y1, Graphics g) {
            // calculate upperleft and width/height of rectangle
            int x = Math.min(x0, x1);
            int y = Math.min(y0, y1);
            int w = Math.abs(x1 - x0);
            int h = Math.abs(y1 - y0);
            // draw rectangle
            g.drawRect(x, y, w, h);
        }
    }

    // if this class is active, ovals are drawn
    class OvalDrawer extends RectangleDrawer {
        @Override
        public void doDraw(int x0, int y0, int x1, int y1, Graphics g) {
            int x = Math.min(x0, x1);
            int y = Math.min(y0, y1);
            int w = Math.abs(x1 - x0);
            int h = Math.abs(y1 - y0);
            // draw oval instead of rectangle
            g.drawOval(x, y, w, h);
        }
    }

    ScribbleDrawer scribbleDrawer = new ScribbleDrawer();
    RectangleDrawer rectDrawer = new RectangleDrawer();
    OvalDrawer ovalDrawer = new OvalDrawer();
    ShapeDrawer currentDrawer;

    public ShapeManager(DrawGUI gui, DrawingPanel drawingPanel) {
        this.gui = gui;
        this.drawingPanel = drawingPanel;

        currentDrawer = scribbleDrawer;
        this.gui.addMouseListener(currentDrawer);
        this.gui.addMouseMotionListener(currentDrawer);
    }

    // reset the shape drawer
    public void setCurrentDrawer(ShapeDrawer l) {
        if (currentDrawer == l)
            return;

        // activate new drawer
        gui.removeMouseListener(currentDrawer);
        gui.removeMouseMotionListener(currentDrawer);
        currentDrawer = l;
        gui.addMouseListener(currentDrawer);
        gui.addMouseMotionListener(currentDrawer);
    }

    // user selected new shape => reset the shape mode
    @Override
    public void itemStateChanged(ItemEvent e) {
        if (e.getItem().equals("Scribble")) {
            setCurrentDrawer(scribbleDrawer);
        } else if (e.getItem().equals("Rectangle")) {
            setCurrentDrawer(rectDrawer);
        } else if (e.getItem().equals("Oval")) {
            setCurrentDrawer(ovalDrawer);
        }
    }
}`


`/**
This class represents a panel for drawing shapes.
It provides methods to clear the image, retrieve the graphics object of the image,
and paint the image on the panel.
*/

package mydraw.gui;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

public class DrawingPanel extends JPanel {

    private static final long serialVersionUID = 1L;
    private BufferedImage image;

    /**
     * 
     * Constructs a new DrawingPanel with a default image size of 800 x 400 pixels.
     * The image is initialized with a white background.
     */
    public DrawingPanel() {
        image = new BufferedImage(800, 400, BufferedImage.TYPE_INT_ARGB);
        clearImage();
    }

    /**
     * 
     * Clears the image by filling it with a white color.
     */
    public void clearImage() {
        Graphics2D g2d = image.createGraphics();
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, image.getWidth(), image.getHeight());
        g2d.dispose();
    }

    /**
     * 
     * Returns the graphics object of the image for drawing shapes on it.
     * 
     * @return the graphics object of the image
     */
    public Graphics2D getImageGraphics() {
        return image.createGraphics();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, null);
    }
}
`

I already tried to "debug" the "doCommand" method using System.out.println and what I found out is that only when clicking "autoDraw" the sentence "autoDraw was pressed" is printed to the console. When clicking the rest of the buttons nothing is printed to the console. Only when I close the application window via the macOS menu, "Quit button was pressed" is output on the console, not via clicking the Quit button itself.

>Solution :

I’m going to edit this into a real answer later, but shot in the dark.

Change this line below.

if (command.equals(CLEAR)) {

Change it to be like this instead.

if (command.equals(DrawGUI.CLEAR)) {

You may need to do some imports.

Leave a Reply