import javax.swing.*; import java.awt.*; import java.awt.event.*; public class TrafficSignal extends JPanel implements ActionListener { private static final int INITIAL_WIDTH = 100; private static final int INITIAL_HEIGHT = 200; private static final double BOX_START_X = 0.2; private static final double BOX_START_Y = 0.1; private static final double BOX_WIDTH = 0.6; private static final double BOX_HEIGHT = 0.8; private static final double BALL_HEIGHT = 0.2; private static final double BALL_WIDTH = 0.4; private static final double BALL_START_X = 0.3; private static final double RED_START_Y = 0.15; private static final double YELLOW_START_Y = 0.40; private static final double GREEN_START_Y = 0.65; public enum State {RED, YELLOW_TO_GREEN, GREEN, YELLOW_TO_RED} private State state; private Timer timer; private int[] intervals; public TrafficSignal(int intervalRed, int intervalYellow, int intervalGreen) { state = State.RED; intervals = new int[] {intervalRed, intervalYellow, intervalGreen}; setPreferredSize(new Dimension(INITIAL_WIDTH, INITIAL_HEIGHT)); timer = new Timer(intervalRed, this); timer.setRepeats(false); timer.start(); } public void paintComponent(Graphics g) { super.paintComponent(g); int width = getWidth(); int height = getHeight(); // draw black box g.setColor(Color.BLACK); g.fillRect((int)(width*BOX_START_X), (int)(height*BOX_START_Y), (int)(width*BOX_WIDTH), (int)(height*BOX_HEIGHT)); int ballWidth = (int)(width*BALL_WIDTH); int ballHeight = (int)(height*BALL_HEIGHT); int ballStartX = (int)(width*BALL_START_X); switch (state) { case RED: g.setColor(Color.RED); g.fillOval(ballStartX, (int)(height*RED_START_Y), ballWidth, ballHeight); break; case YELLOW_TO_GREEN: case YELLOW_TO_RED: g.setColor(Color.YELLOW); g.fillOval(ballStartX, (int)(height*YELLOW_START_Y), ballWidth, ballHeight); break; case GREEN: g.setColor(Color.GREEN); g.fillOval(ballStartX, (int)(height*GREEN_START_Y), ballWidth, ballHeight); break; } } public void actionPerformed(ActionEvent e) { state = State.values()[(state.ordinal() + 1) % State.values().length]; switch (state) { case RED: //timer.stop(); timer.setInitialDelay(intervals[0]); timer.start(); break; case YELLOW_TO_GREEN: case YELLOW_TO_RED: //timer.stop(); timer.setInitialDelay(intervals[1]); timer.start(); break; case GREEN: //timer.stop(); timer.setInitialDelay(intervals[2]); timer.start(); break; } repaint(); } public static void main(String[] args) { JFrame fr = new JFrame(); fr.add(new TrafficSignal(1500,100,1500), BorderLayout.CENTER); fr.pack(); fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); fr.setVisible(true); } }