-2

I'm currently working on a Stoplight, which changes lights automatically.

What I have: I currently have a code for a Stoplight that works with a button press.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

/**
  *
  * Beschreibung
  *
  * @version 1.0 vom 23.01.2017
  * @author 
  */

public class ampel extends JApplet {
  // Anfang Attribute
  private JLabel jLabel1 = new JLabel();
  private JLabel jLabel2 = new JLabel();
  private JLabel jLabel3 = new JLabel();
  private JButton jButton1 = new JButton();
  private JButton jButton2 = new JButton();
  private JButton jButton3 = new JButton();
  private JButton jButton4 = new JButton();
  private JLabel jLabel4 = new JLabel();
  private JLabel jLabel5 = new JLabel();
  private JLabel jLabel6 = new JLabel();
  // Ende Attribute

  public void init() {
    Container cp = getContentPane();
    cp.setLayout(null);
    cp.setBounds(0, 0, 314, 300);
    // Anfang Komponenten
    jButton1.setVisible(true);
    jButton2.setVisible(false);
    jButton3.setVisible(false);
    jButton4.setVisible(false);
    jLabel1.setBounds(16, 24, 75, 41);
    jLabel1.setText("");
    jLabel1.setOpaque(true);
    cp.add(jLabel1);
    jLabel2.setBounds(16, 88, 75, 33);
    jLabel2.setText("");
    jLabel2.setOpaque(true);
    cp.add(jLabel2);
    jLabel3.setBounds(16, 144, 75, 33);
    jLabel3.setText("");
    jLabel3.setOpaque(true);
    cp.add(jLabel3);
    jButton1.setBounds(112, 96, 73, 25);
    jButton1.setText("jButton1");
    jButton1.setMargin(new Insets(2, 2, 2, 2));
    jButton1.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        jButton1_ActionPerformed(evt);
      }
    });
    cp.add(jButton1);
    jButton2.setBounds(112, 96, 73, 25);
    jButton2.setText("jButton2");
    jButton2.setMargin(new Insets(2, 2, 2, 2));
    jButton2.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        jButton2_ActionPerformed(evt);
      }
    });
    cp.add(jButton2);
    jButton3.setBounds(112, 96, 73, 25);
    jButton3.setText("jButton3");
    jButton3.setMargin(new Insets(2, 2, 2, 2));
    jButton3.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        jButton3_ActionPerformed(evt);
      }
    });
    cp.add(jButton3);
    jButton4.setBounds(112, 96, 73, 25);
    jButton4.setText("jButton4");
    jButton4.setMargin(new Insets(2, 2, 2, 2));
    jButton4.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        jButton4_ActionPerformed(evt);
      }
    });
    cp.add(jButton4);
    cp.setBackground(new Color(0xC0C0C0));
    jLabel4.setBounds(224, 16, 75, 49);
    jLabel4.setText("");
    jLabel4.setBackground(Color.WHITE);
    jLabel4.setOpaque(true);
    cp.add(jLabel4);
    jLabel5.setBounds(224, 80, 75, 49);
    jLabel5.setText("");
    jLabel5.setBackground(Color.WHITE);
    jLabel5.setOpaque(true);
    cp.add(jLabel5);
    jLabel6.setBounds(224, 144, 75, 33);
    jLabel6.setText("");
    jLabel6.setBackground(Color.WHITE);
    jLabel6.setOpaque(true);
    cp.add(jLabel6);
    // Ende Komponenten

  } // end of init

  // Anfang Methoden
  public void jButton1_ActionPerformed(ActionEvent evt) {
    jButton2.setVisible(true);
    jButton1.setVisible(false);

    jLabel1.setBackground(new Color(255,0,0));
    jLabel2.setBackground(new Color(255,255,255));
    jLabel3.setBackground(new Color(255,255,255));

    jLabel4.setBackground(new Color(255,255,255));
    jLabel5.setBackground(new Color(255,255,255));
    jLabel6.setBackground(new Color(0,255,0));
  } // end of jButton1_ActionPerformed

  public void jButton2_ActionPerformed(ActionEvent evt) {
    jButton3.setVisible(true);
    jButton2.setVisible(false);
    jLabel1.setBackground(new Color(255,0,0));
    jLabel2.setBackground(new Color(255,255,0));
    jLabel3.setBackground(new Color(255,255,255));

    jLabel4.setBackground(new Color(255,255,255));
    jLabel5.setBackground(new Color(255,255,0));
    jLabel6.setBackground(new Color(255,255,255));
  } // end of jButton2_ActionPerformed

  public void jButton3_ActionPerformed(ActionEvent evt) {
    jButton4.setVisible(true);
    jButton3.setVisible(false);
    jLabel1.setBackground(new Color(255,255,255));
    jLabel2.setBackground(new Color(255,255,255));
    jLabel3.setBackground(new Color(0,255,0));

    jLabel4.setBackground(new Color(255,0,0));
    jLabel5.setBackground(new Color(255,255,255));
    jLabel6.setBackground(new Color(255,255,255));
  } // end of jButton3_ActionPerformed

  public void jButton4_ActionPerformed(ActionEvent evt) {
    jButton1.setVisible(true);
    jButton4.setVisible(false);
    jLabel1.setBackground(new Color(255,255,255));
    jLabel2.setBackground(new Color(255,255,0));
    jLabel3.setBackground(new Color(255,255,255));

    jLabel4.setBackground(new Color(255,0,0));
    jLabel5.setBackground(new Color(255,255,0));
    jLabel6.setBackground(new Color(255,255,255));
  } // end of jButton4_ActionPerformed

  // Ende Methoden

} // end of class ampel

Now to my Problems:

  1. Seemingly my appletviewer is bugged. (Screenshots of my linked Code, buttonpress Stoplight)

enter image description here

enter image description here

These 2 Gif's should give you an idea.

  1. I've read through several articles in how to make a timer and methods, but i don't really know now How to implement it into my source code or change it so it works with a timer.

I understood it like this:

Make a Method which says do x,y,z...

public void timer1_ActionPerformed(ActionEvent evt) {

    timer.setInitialDelay

    // tell him to do x

    Thread.sleep(5000); // or something similare so it will wait 5 seconds

    // Tell him to do y
    // wait

    // Tell him to do z
    // ...repeat
}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
Shaddy
  • 11
  • 2
  • 2
    where is your code ? – Mohsen_Fatemi Jan 24 '17 at 21:10
  • I made it stood out in Bold text in my edit. – Shaddy Jan 24 '17 at 21:14
  • I would "guess" your problem starts with using an Applet and runs into `Thread.sleep(5000);`, which is probably blocking the EDT and preventing the UI from been updated. Applets are deprecated (maybe not in the JDK, but in life), almost all browser either actively block them or have dropped support for them, better to just avoid them altogether. At a "guess", you're using a Swing `Timer`, which is the right direction, but the `Timer` will do the waiting for you, you don't need to do any yourself. Think of the `Timer` as a pseudo loop, each tick is an iteration of the loop – MadProgrammer Jan 24 '17 at 21:16
  • You're also overriding `paint` or one of it's variants and not calling `super.paint` ... you broke it – MadProgrammer Jan 24 '17 at 21:17
  • @MadProgrammerthe Thread.sleep(5000); was just a solution i found, it is not implemented in the Gifs, since i don't know how yet. – Shaddy Jan 24 '17 at 21:33
  • To expand on @MadProgrammer's comment, you're using a `null` layout and it's probably part of your problem. Instead you might want to use a [layout manager](https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html) with [Empty borders](https://docs.oracle.com/javase/tutorial/uiswing/components/border.html) for extra spacing between components... – Frakcool Jan 24 '17 at 22:09
  • 2
    ... Please take a look at [Null layout is evil](http://www.leepoint.net/GUI/layouts/nulllayout.html) and [Why is it frowned upon to use a null layout in swing?](http://stackoverflow.com/questions/6592468/why-is-it-frowned-upon-to-use-a-null-layout-in-swing) for more information about this bad practice. Also you might want to read what a [mcve] or [Short, Self Contained, Correct Example](http://sscce.org/) are and post them in your question as code-formatted text and not in external sites. – Frakcool Jan 24 '17 at 22:09
  • Code should be posted in the forum. – camickr Jan 24 '17 at 22:18
  • Again, where is your code? It should always be posted in your question as code-formatted text, and you've been asked to show it 1 hour ago and 2 hours ago, but still no code -- why? – Hovercraft Full Of Eels Jan 24 '17 at 23:18
  • 1
    @cricket_007 It apparently is a relative path for hastebin.com. I found the OP's code here (or at least I think so): https://hastebin.com/liqedavule.java – The SE I loved is dead Jan 24 '17 at 23:31
  • Regardless, the original poster (OP) should read the rules and regs before posting, or in the least should respond to our requests for code in the question itself. – Hovercraft Full Of Eels Jan 24 '17 at 23:35
  • @MadProgrammer Now with self contained code in question. Time to re-open? – Andrew Thompson Jan 24 '17 at 23:43
  • @HovercraftFullOfEels Now with self contained code in question. Time to re-open? – Andrew Thompson Jan 24 '17 at 23:43
  • @AndrewThompson: so voted – Hovercraft Full Of Eels Jan 24 '17 at 23:44
  • Although I'm not changing my down-vote since it's not the OP who made the change. – Hovercraft Full Of Eels Jan 24 '17 at 23:44
  • @HovercraftFullOfEels *"not changing my down-vote"* Sounds reasonable. They probably should have got the message earlier. – Andrew Thompson Jan 24 '17 at 23:46
  • 1
    Not seeing any issues with the initially posted code, works fine on Mac OS :P – MadProgrammer Jan 24 '17 at 23:51

1 Answers1

3

There are some problems in your code:

  1. You're using a null layout, which is a bad practice, because it will lead to some layout specific problems, including repainting (probably your "buggy" GUI is because of this 1st problem), see Null layout is evil and Why is it frowned upon to use a null layout in Swing? to know why it's a bad practice to use them.

    While pixel perfect applications and the use of setBounds() might seem like the best way to build complex GUIs for Swing newbies, the more you do, the more problems you'll face due to this and you'll have a hard time trying to fix them, instead try using a layout manager or combinations of them along with empty borders for extra space between components.

  2. You're playing with the visibility of the JButtons, you could instead use a Card Layout or have a single JButton that manages all these events. This way you only need to handle a single action and not many (which in the end are the same).

  3. You're using a JApplet, which as said before in the comment of @MadProgrammer:

    Applets are deprecated (maybe not in the JDK, but in life), almost all browser either actively block them or have dropped support for them, better to just avoid them altogether

    You might want to use a JPanel instead and check this really interesting post about why CS teachers should stop teaching Applets.

  4. While you're changing your program from a JApplet to a JPanel based application, you should place your program on the Event Dispatch Thread (EDT) which could cause threading problems. An easy way to fix this is to make your main method as follows:

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                //Place your constructor here
            }
        });
    }
    
  5. You're not following the Java naming conventions since your class is named ampel which should start with a CapitalLetter as Ampel.


After those recommendations, you can get a really similar GUI with the following code:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class StopLightSample {

    private JFrame frame;
    private JPanel pane;
    private JPanel leftPane;
    private JPanel centerPane;
    private JPanel rightPane;
    private JPanel[] leftLights;
    private JPanel[] rightLights;
    private JButton button;
    private int leftLightFocus = 0;
    private int rightLightFocus = 2;
    private Color[] leftColors = {Color.GREEN, Color.YELLOW, Color.RED};
    private Color[] rightColors = {Color.RED, Color.YELLOW, Color.GREEN};
    private Timer timer;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new StopLightSample().createAndShowGui();
            }
        });
    }

    private ActionListener actionListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            for (int i = 0; i < 3; i++) {
                leftLights[i].setBackground(Color.WHITE);
                rightLights[i].setBackground(Color.WHITE);
            }

            leftLights[leftLightFocus].setBackground(leftColors[leftLightFocus]);
            rightLights[rightLightFocus].setBackground(rightColors[rightLightFocus]);

            leftLightFocus++;
            rightLightFocus--;

            if (leftLightFocus > 2) {
                leftLightFocus = 0;
            }

            if (rightLightFocus < 0) {
                rightLightFocus = 2;
            }
        }
    };

    public void createAndShowGui() {
        frame = new JFrame("Stoplight sample");
        pane = new JPanel();
        pane.setLayout(new GridLayout(1, 3, 20, 5));
        leftLights = new JPanel[3];
        rightLights = new JPanel[3];
        button = new JButton("Button");

        leftPane = new JPanel();
        rightPane = new JPanel();

        centerPane = new JPanel();
        centerPane.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 100));

        button.addActionListener(actionListener);

        centerPane.add(button);

        leftPane.setLayout(new GridLayout(3, 1, 0, 25));
        rightPane.setLayout(new GridLayout(3, 1, 0, 25));

        for (int i = 0; i < 3; i++) {
            leftLights[i] = new JPanel() {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(100, 50);
                }
            };

            rightLights[i] = new JPanel() {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(100, 50);
                }
            };

            leftLights[i].setBackground(Color.WHITE);
            rightLights[i].setBackground(Color.WHITE);

            leftLights[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));
            rightLights[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));

            leftPane.add(leftLights[i]);
            rightPane.add(rightLights[i]);
        }

        pane.add(leftPane);
        pane.add(centerPane);
        pane.add(rightPane);

        frame.add(pane);

        timer = new Timer(1000, actionListener);
        timer.setInitialDelay(0);
        timer.start();

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

enter image description here enter image description here enter image description here

As you can see, both (the button and the Timer) listen to the same actionListener, so there's no need to use a lot of them (as said before on the point #2).

I think I'm not missing anything and hope that helps you, however you should be posting your code in your question (as I did in my answer). Please read how to make a valid Minimal, Complete and Verifiable Example (MCVE) or a Short, Self Contained, Correct Example (SSCCE) for your next questions, so they don't get downvoted because of this.

Community
  • 1
  • 1
Frakcool
  • 10,915
  • 9
  • 50
  • 89