CrazyBacon
CrazyBacon

Reputation: 55

JFrame: Sleep between statements

I'm still very new to the world of programming and have recently noticed, that whenever I tell the programm to idle for some seconds between the code, it instead sleeps at the start and then goes through the remaining code.

I've tried various ways like thread.sleep() or Timers but I never get what I want.

Here is an example:

public void Console(){

        Console.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        Console.setSize(500, 500);
        Console.setLocationRelativeTo(null);
        Console.setResizable(false);
        Console.setVisible(true);
        Console.setTitle("Console");

        JPanel contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));

        Console.setContentPane(contentPane);
        contentPane.setLayout(null);
        contentPane.setBackground(new Color(47, 79, 79));

        cinput.setBounds(10, 442, 353, 20);
        contentPane.add(cinput);

        cinput.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {

                in();

                cinput.requestFocus();

            }
        });

        cinput.setColumns(10);
        cinput.requestFocus();

        JButton Enter = new JButton("Enter");
        Enter.setBounds(373, 439, 111, 23);
        contentPane.add(Enter);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(10, 10, 474, 421);
        contentPane.add(scrollPane);

        cmd.setEditable(false);
        cmd.setFont(new Font("Courier New", Font.PLAIN, 18));
        cmd.setForeground(Color.GREEN);
        cmd.setText("CONSOLE\n");
        cmd.setBackground(Color.BLACK);
        cmd.setLineWrap(true);
        cmd.setWrapStyleWord(true);


        scrollPane.setViewportView(cmd);

        Enter.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent arg0) {

            in();

            cinput.requestFocus();
            }
        });

    }

    private void addText(JTextArea textArea, String text) {

        String input = textArea.getText();
        String output = input + text;

        textArea.setText(output);
    }

    private void in()
    {
        String input = cinput.getText();
        cinput.setText("");

        String text;

        text = input;

        addText(cmd, "> " + text + "\n");

        if(text.equals("start"))
        {
            addText(cmd, "1");

            // SLEEP HERE

            Thread.sleep(1000); 

           // -------------------

            addText(cmd, "2");


        }
        else if(text.equals("exit"))
        {   
            Console.dispose();
        }
    }

It should look something like this:

enter image description here

In this very basic 'Console', whenever I type 'start' in the textbox and hit enter, I want the number '1' to appear first and after 1000 mseconds the number '2' should appear, which it doesn't!

Is there any way to tell the programm to sleep between statements instead of always sleeping at the beginnig of the function?

Thanks in advance

Upvotes: 1

Views: 1773

Answers (3)

Dima Maligin
Dima Maligin

Reputation: 1482

It looks like you are trying to put to sleep the main Thread which is not the best idea. Run your own Thread and put it to sleep.

Try this:

System.out.println(1);
SwingUtilities.invokeLater(() -> {
    new Timer(1000, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println(2);
        }
    }).start();
});

You can also do this without Thread.sleep():

long tick = 1000;
long startTime = System.currentTimeMillis();

while (true) {
    long now = System.currentTimeMillis();
    while (now - startTime > tick) {
        System.out.println("Seconds from start time: " + (int) (tick / 1000));
        tick += 1000;
    }
}

If it suites you just tweak the above example for your needs(it also accounts for possible lag so the number of seconds will still be correct).

Upvotes: 2

Emily Crutcher
Emily Crutcher

Reputation: 658

While technically the answers above are true, your problem is

  1. You must do all Swing work on the Swing Event Dispatch Thread.
  2. You really, really, don't want to sleep the main Swing Event Dispatch Thread!

What you want to do instead is create a helper class that wraps the javax.swing.Timer (NOT the java.util.timer) that allows you to easily run code on the event thread after a certain number of milliseconds has passed.

public abstract class LazyAction implements Runnable { 

    public LazyAction(int millis) {
        Timer t = new Timer(millis, new ActionListener() {

                        @Override
                        public void actionPerformed(ActionEvent e) {
                         try{
                            LazyAction.this.run();
                         catch(Exception e){
                            //Your error handling code
                         }
                        }

                    });
                    t.setRepeats(false);
                    t.start();
       }}

Now, to use this code, you then call it by:

  addText(cmd, "1");
  new LazyAction(300){

        @Override
        public void run() {
           addText(cmd, "2");
        }
  }

(Note if you are using Java 8 you could use Lambdas instead, in that case LazyAction would take in a Runnable rather than implementing Runnable...)

Upvotes: 4

MobileMon
MobileMon

Reputation: 8651

Put a sleep statement before adding the first line of text:

Thread.sleep(1000);
addText(cmd, "1");

 // SLEEP HERE

Thread.sleep(1000); 

// -------------------

addText(cmd, "2");

Upvotes: 0

Related Questions