LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Java: Delay (sleep, wait or whatever) within the ActionPerformed function (http://www.linuxquestions.org/questions/programming-9/java-delay-sleep-wait-or-whatever-within-the-actionperformed-function-4175432749/)

rm_-rf_windows 10-17-2012 03:18 PM

Java: Delay (sleep, wait or whatever) within the ActionPerformed function
 
Hi all,

I've got this little game. There are two players, one of which is the machine.

When the player plays, the ActionPerformed (Java, Swing) function not only makes necessary changes on the Frame/Panel, but the machine also makes a move. I would like to insert a delay (a random delay if possible, between 500 and 2500 milliseconds) between the time the player makes the move and the time the machine does (which is not an "ActionPerformed") so as to give the human player the impression that the machine is thinking.

In other words, here's what I'd like (the code below does NOT work):
Code:

public void actionPerformed(ActionEvent ae){
 System.out.println("This represents the change on the display corresponding to the human player's move");
sleep(1000); // or random delay between 500 and 2500 ms
 System.out.println("This represents the machine's move, which is not an actual performed action or action event");
}

There must be an easy way to do this (maybe not?).

I've Google it but can't seem to find a simple solution.

Thanks in advance,

rm

amboxer21 10-18-2012 02:32 AM

You could use Thread.sleep or thread.wait

With Thread.sleep, the thread stops working for the time you specified.

With Thread.wait, the thread stops working until the object being waited-on is notified, generally by other threads.

rm_-rf_windows 10-18-2012 06:44 PM

Thanks for your reply amboxer21!

Okay, you are right. I'd already tried that and initially thought it wouldn't work then played with it a bit (see code below). I now realize that my problem isn't quite what I described initially...

In the following code, I'd like the "X" to appear when the left button is pressed (immediately) and then a 2 second pause followed by the "O" appearing on the right-hand button. When running this little program, the System.out.println messages are displayed one after the other with the appropriate pause, however both the "X" and "O" appear at the same time in the window 2 seconds after the left-hand button is pressed:

Code:

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

public class SleepTest implements ActionListener {

    private JFrame window = new JFrame("SleepTest");
    private JButton button1 = new JButton();
    private JButton button2 = new JButton();

    public SleepTest() {
        window.setPreferredSize(new Dimension(300, 150));
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.add(button1);
        window.add(button2);
        button1.addActionListener(this);
        button2.addActionListener(this);
        window.setVisible(true);
        window.setLayout(new GridLayout(1, 2));
        window.pack();
    }

    public void actionPerformed(ActionEvent ae) {
        button1.setText("X");
        button1.setEnabled(false);
        System.out
                .println("PLAYER ACTION: This represents the change on the display corresponding to the human player's move");
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException ie) {
            // ... Error message...
        }
        System.out
                .println("MACHINE ACTION: This represents the machine's move, which is not an actual performed action or action event");
        button2.setText("O");
    }

    public static void main(String[] args) {
        new SleepTest();
    }
}

If anybody out there could modify my code so that it does what I want it to do, I'd certainly appreciate it.

Many thanks,

rm

ntubski 10-19-2012 01:16 AM

Quote:

Originally Posted by rm_-rf_windows (Post 4809516)
When running this little program, the System.out.println messages are displayed one after the other with the appropriate pause, however both the "X" and "O" appear at the same time in the window 2 seconds after the left-hand button is pressed:

It's because the repainting code happens in the same thread as the event handling. What you need to do is set a Timer to make the "O" later on (completely untested):
Code:

public class SleepTest implements ActionListener {
...
    private JButton button2 = new JButton();
    private ButtonTextSetter button2SetO = new ButtonTextSetter(button2, "O");
    private Timer machineMoveTimer = new Timer(2000, button2SetO);

    public SleepTest() {
        machineMoveTimer.setRepeats(false);
        ...
    }
...
    public void actionPerformed(ActionEvent ae) {
        button1.setText("X");
        button1.setEnabled(false);

        machineMoveTimer.restart();
    }
...
}

class ButtonTextSetter implements ActionListener {
    final AbstractButton button;
    final String text;

    ButtonTextSetter(AbstractButton button, String text) {
        this.button = button;
        this.text = text;
    }

    public void actionPerformed(ActionEvent ae) {
        button.setText(text);
    }
}


rm_-rf_windows 10-19-2012 05:21 PM

Thanks ntubski! It works!!

Here's the complete code (for those who are new to using or not really used to using ActionListener stuff, such as me):

Code:

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

public class SleepTestWithTimer implements ActionListener {

    private JFrame window = new JFrame("SleepTestWithTimer");
    private JButton button1 = new JButton();
    private JButton button2 = new JButton();
    private ButtonTextSetter button2SetO = new ButtonTextSetter(button2, "O");
    private Timer machineMoveTimer = new Timer(2000, button2SetO);

    public SleepTestWithTimer() {
        window.setPreferredSize(new Dimension(300, 150));
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.add(button1);
        window.add(button2);
        button1.addActionListener(this);
        button2.addActionListener(this);
        window.setVisible(true);
        window.setLayout(new GridLayout(1, 2));
        window.pack();
        machineMoveTimer.setRepeats(false);
    }

    public void actionPerformed(ActionEvent ae) {
        button1.setText("X");
        button1.setEnabled(false);
        machineMoveTimer.restart();
    }
   
    public static void main(String[] args) {
        new SleepTestWithTimer();
    }
}

class ButtonTextSetter implements ActionListener {
    final AbstractButton button;
    final String text;

    ButtonTextSetter(AbstractButton button, String text) {
        this.button = button;
        this.text = text;
    }

    public void actionPerformed(ActionEvent ae) {
        button.setText(text);
    }
}

Many thanks!

rm


All times are GMT -5. The time now is 06:21 PM.