0

I'm working on a project that involves access by reading a String from a physical card, the following code simplifies the main point of my program, however when I try to make a pause for a few seconds after an user has swipe his card, something goes wrong and the behavior is not what I need, the program pauses but the color's pane doesn't change nor the label.

Any suggestion?

This is the code:

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

public class B2 extends JFrame implements ActionListener {
JLabel lbl;
JButton btn;
JTextField jtf;
String password = "123";

public B2() {
    super("");

    this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    this.setLayout(null);
    this.setVisible(true);

    setBounds(0,0,480, 250);
    getContentPane().setBackground(Color.cyan);

    btn = new JButton("OK");
    lbl = new JLabel("Enter your password");
    jtf = new JTextField(25);

    btn.addActionListener(this);
    lbl.setBounds(50, 100, 200, 25);
    btn.setBounds(150, 180, 110, 25);
    jtf.setBounds(20, 180, 110, 25);

    getContentPane().add(btn);
    getContentPane().add(lbl);
    getContentPane().add(jtf);
 }

public void actionPerformed(ActionEvent e) {

    if(jtf.getText().equals(password)) {
        getContentPane().setBackground(Color.green);
        lbl.setText("Welcome");
    } else {
        getContentPane().setBackground(Color.red);
        lbl.setText("Access Denied");
    }

    try {
        Thread.sleep(3000);
    } catch (InterruptedException e1) {
        e1.printStackTrace();
    }

    getContentPane().setBackground(Color.cyan);
    lbl.setText("Enter your password");
}

  public static void main(String[] args) {

  javax.swing.SwingUtilities.invokeLater(new Runnable() {
         @Override
         public void run() {
             B2 frame = new B2();
         }
      });
}
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 2
    _Don't_ sleep on the EDT; _do_ see [*Concurrency in Swing*](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/). – trashgod Mar 18 '15 at 06:42
  • Yes, but not the way you are doing it. Better to use a Swing Timer – MadProgrammer Mar 18 '15 at 07:10
  • `this.setLayout(null);` Java GUIs have to work on different OS', screen size, screen resolution etc. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). – Andrew Thompson Mar 18 '15 at 07:19
  • As an aside, if you are waiting on the user to supply a value, better to change the `JFrame` to a modal `JDialog or a `JOptionPane`. That will 'block' access to the GUI and the next code line, until the dialog is dismissed. – Andrew Thompson Mar 18 '15 at 07:22
  • Thanks everybody for your useful comments, they're very important for me. – Máximo Soria Mar 18 '15 at 18:47

2 Answers2

1

Using Thread.sleep() prevents Swing from doing a repaint until the pause has finished. So it will change the color and change it back at the same time and you won't see the effect.

Try to use a Timer instead. Add this to your code and it will work:

if(jtf.getText().equals(password)) {
    getContentPane().setBackground(Color.green);
    lbl.setText("Welcome");

} else {
    getContentPane().setBackground(Color.red);
    lbl.setText("Access Denied");
}

Timer timer = new Timer(3000, new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        getContentPane().setBackground(Color.cyan);
        lbl.setText("Enter your password");
    }
});
timer.setRepeats(false);
timer.start();
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Jefe infiltrado
  • 364
  • 2
  • 15
-2

put last 2 lines in comment

//getContentPane().setBackground(Color.cyan);

//lbl.setText("Enter your password");

you will see effect only when action is performed. when actionPerformed() is executed. hope you got your solution

Rahul Gulwani
  • 198
  • 4
  • 18