How to define multiple JButton actions from a different class

Use Action to encapsulate functionality for use elsewhere in your program, e.g. buttons, menus and toolbars. The BeaconPanel shown below exports several actions that make it easy to use them in a control panel. To limit the proliferation of instances, the actions themselves can be class members. As an exercise, change controls to a JToolBar or add the same actions to a menu.

JPanel controls = new JPanel();
controls.add(new JButton(beaconPanel.getFlashAction()));
controls.add(new JButton(beaconPanel.getOnAction()));
controls.add(new JButton(beaconPanel.getOffAction()));

image

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Timer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

/** @see http://stackoverflow.com/a/37063037/230513 */
public class Beacon {

    private static class BeaconPanel extends JPanel {

        private static final int N = 16;
        private final Ellipse2D.Double ball = new Ellipse2D.Double();
        private final Timer timer;
        private final Color on;
        private final Color off;
        private final AbstractAction flashAction = new AbstractAction("Flash") {
            @Override
            public void actionPerformed(ActionEvent e) {
                timer.restart();
            }
        };
        private final AbstractAction onAction = new AbstractAction("On") {
            @Override
            public void actionPerformed(ActionEvent e) {
                stop(on);
            }
        };
        private final AbstractAction offAction = new AbstractAction("Off") {
            @Override
            public void actionPerformed(ActionEvent e) {
                stop(off);
            }
        };
        private Color currentColor;

        public BeaconPanel(Color on, Color off) {
            this.on = on;
            this.off = off;
            this.currentColor = on;
            timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    changeColors();
                }
            });
        }

        public void start() {
            timer.start();
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
            int x = getX() + N;
            int y = getY() + N;
            int w = getWidth() - 2 * N;
            int h = getHeight() - 2 * N;
            ball.setFrame(x, y, w, h);
            g2.setColor(currentColor);
            g2.fill(ball);
            g2.setColor(Color.black);
            g2.draw(ball);
        }

        private void changeColors() {
            currentColor = currentColor == on ? off : on;
            repaint();
        }

        private void stop(Color color) {
            timer.stop();
            currentColor = color;
            repaint();
        }

        public Action getFlashAction() {
            return flashAction;
        }

        public Action getOnAction() {
            return onAction;
        }

        public Action getOffAction() {
            return offAction;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(N * N, N * N);
        }
    }

    public static void display() {
        JFrame f = new JFrame("Beacon");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final BeaconPanel beaconPanel = new BeaconPanel(Color.orange, Color.orange.darker());
        f.add(beaconPanel);
        JPanel controls = new JPanel();
        controls.add(new JButton(beaconPanel.getFlashAction()));
        controls.add(new JButton(beaconPanel.getOnAction()));
        controls.add(new JButton(beaconPanel.getOffAction()));
        f.add(controls, BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        beaconPanel.start();
    }

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

Leave a Comment