-1

I am trying to create a traffic light using a Java GUI, where it displays only one circle and it changes colours from red, to yellow, to green. There should be a timer and only yellow should be changing to green within 3 seconds. I have set up a circle and a colour red, but I am unable to change it to the colours yellow, and green respectively using a timer.

Btw I am really new to GUI and could not find helpful sources online, although I still watched a couple of youtube videos but did not find anything useful or relevant to this task. Any help would be much appreciated!

Code:

import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Color;
import javax.swing.JFrame;

public class Main extends Canvas {
public static void main(String[] args) {
    JFrame frame = new JFrame();
    Canvas canvas = new Main();
    canvas.setSize(700, 700);
    frame.add(canvas);
    frame.pack();
    frame.setVisible(true);
}

public void paint(Graphics g) {
    g.setColor(Color.red);
    g.fillOval(200, 200, 300, 300);
   }
}

Expected Output:

It should be only one circle

  • 1
    *using a timer.* - well, you haven't posted any Timer code, so we can't guess what you may or may not have tried. We are not here to write the code for you. After following my suggestion below, if you still need help, then post a proper [mre] demonstrating the problem. – camickr Sep 30 '20 at 19:54
  • (1-) *but did not find anything useful or relevant to this task.* - Of course you won't find the exact code for your assignment. I gave you a complete working example of how to use a Swing Timer. The point is for you to understand the basic concept of the Timer and then write the code for your specific requirement. – camickr Oct 01 '20 at 00:45

2 Answers2

1
  1. Don't extend Canvas. Custom painting in Swing is done by extending JPanel and by overriding the paintComponent() method. Read the section from the Swing tutorial on Custom Painting for more information and working examples.

  2. A painting method should only paint the current state of the class. So you would need to add a method like setLightColor(Color lightColor) to your component that does the custom painting. Then in the painting method you use that value for the Color of your circle (instead of hard coding "RED"). Or you have a method like changeLight() that updates a varable from 0, 1, 2, 0, 1, 2... . Then in the painting method you you check the state of the variable and paint the appropriate color.

  3. You need to use a Swing Timer to schedule an event. When the Timer fires you invoke the setLightColor(...) method on your class.

  4. The Timer should be part of your class that does the custom painting. You should have a method that can start/stop the Timer.

You can check out: https://stackoverflow.com/a/7816604/131872 for a basic example of the Swing Timer.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • Could you show me a sample with my code. I am new to GUI so I basically got no clue at all –  Sep 30 '20 at 20:51
  • 1
    I gave you multiple examples. You have not updated your question with the [mre] showing what you have tried. We are not here to write the code for you. You learn by trying. So take working code and make changes. The first step would be to take the code from the custom painting tutorial and understand the basics of how to do custom painting properly. Then you add the Timer logic. Solve the problem one step at a time. – camickr Oct 01 '20 at 00:55
1

Here is one approach. The lights stay on for 3 seconds. To change their duration the code must be modified accordingly. This would be done inside the timer.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class TrafficLight extends JPanel {
    JFrame frame = new JFrame();
    
    int colorIdx = 0;
    Color[] colors = { Color.green, Color.yellow, Color.red };
    
    public static void main(String[] args) {
        // Ensure the program is started on the Event Dispatch Thread
        SwingUtilities.invokeLater(() -> new TrafficLight().start());
    }
    
    public void start() {
        // set up
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // set the preferred size. Okay in this instance but best
        // practice dictates to override getPreferredSize()
        setPreferredSize(new Dimension(500, 500));
        
        frame.add(this);
        frame.pack();
        
        // center on screen
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        
        Timer t = new Timer(3000, ae -> {
            colorIdx = colorIdx >= 2 ? 0 : colorIdx + 1;
            repaint();
        });
        t.start();
    }
    
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        g.setColor(colors[colorIdx]);
        g.fillOval(150, 150, 200, 200);
        
    }
    
}
WJS
  • 36,363
  • 4
  • 24
  • 39