Hello,
My program needs to capture the screen every 1 second until stopped by pressing the GUI button.
In the GUI class I used a for loop to go infinite, but that probably does not work because it takes time to capture, & save screenshot, but the for loop fires before that, thus giving errors, and IO exceptions.
I am now trying to sleep/wait the program somehow for 1-2 seconds between each shot taken.
Unfortunately, I am unable to get the "thread" code going write. May be too confused.
Can someone please modify the below to use "threads", which waits 2 seconds between each shot taken?

public class ScreenShotRobot {

boolean captureScreenShot(String uploadPath, String mode, String filename){
boolean isSuccesful = false;
Rectangle screenRect = new Rectangle( Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage capture;
try {

capture = new Robot().createScreenCapture(screenRect);
ImageIO.write(capture, mode, new File( uploadPath, filename));
//should wait here for 2 seconds, then loop back
isSuccesful = true;
}catch( Exception e ){ isSuccesful = false; }
return isSuccesful;
}
}

try the bellow code for your requirement

try {    

    capture = new Robot().createScreenCapture(screenRect);
    ImageIO.write(capture, mode, new File( uploadPath, filename));

    // this makes 2 sec sleep
    Thread.currentThread.sleep(2000);  // here 2000 means 2 sec     
}
}catch(Exception e){
     // your remaining code 
}

Hi,
The problem is that the code is not in a thread & I don't know how to fit it in a thread.

The above class is being called from a different class which forms the GUI.
In the GUI when "start" button is clicked, the following executes:

for(int x=1;;x++){
fn= Integer.toString(x) + "filename.jpg";
ScreenShotRobot.captureScreenShot( "folder/", "jpg", fn );
}

The above is inside the actionListener of a JButton

How do I put these 2 classes together so that when "start" button is pressed, it starts a thread, which loops infinitely, and waits 2 seconds each run.

so then take a global variable for continuing (screen capture) the loop as folllow

public static boolean loop_status = true

and then modify your code as follows (here we are making the total process of your work in a seperate thread so that its never distrub the main thread at all)

new Thread(new Runnable(){

public void run(){
   try{
        for(int x=1;;x++) 
        {
             fn= Integer.toString(x) + "filename.jpg";
             ScreenShotRobot.captureScreenShot( "folder/", "jpg", fn );
             Thread.currentThread().sleep(2000);
             if(!loop_status){ // this loops until the value of the variable changed to false
             break;
             }
        }
}catch(Exception e ){
      // handling code if any exception raises here
}

}

}).start()

whenever you want to stop the screen capturing then try make the loop_status variable value to false

pls try to make changes in your code

let me know whether this is woirking perfectly or not

happy coding

Edited 3 Years Ago by radhakrishna.p: giving vlarity on the solution

Be aware that if you plan to modify loop_status in one thread and read it in another thread without synchronization then it should be declared volatile to ensure that both threads have the same value.

For example: public static volatile boolean loop_status = true;

Otherwise it is possible that loop_status in your screen capture thread won't change when you change loop_status in the event dispatch thread.

Edited 3 Years Ago by bguild

Hi,
The thread now sleeps (thanks), but program doesn't end when "stop" button is clicked. I've to windows "end task" to stop it.

int loop_status=1;

//for start button
new ActionListener(){
public void actionPerformed( ActionEvent event ){

loop_status=1;
try{
for(int x=1;;x++){

fn= Integer.toString(x) + "s.jpg";
i = sc.captureScreenShot( s, "jpg", fn );

Thread.currentThread().sleep(2000);
if(loop_status==0){ break; }
}//for
}catch( Exception te ){ }

}//event
}//listener


//for stop button
new ActionListener(){
public void actionPerformed( ActionEvent event ){

loop_status=0;

}
}

You should never call Thread.sleep in the event dispatch thread and you should never go into an infinite loop in the event dispatch thread. All calls to actionPerformed happen in the event dispatch thread, so no calls to actionPerformed can happen as long as your loop is running. That means that your loop_status cannot be set to zero, and your GUI cannot be updated in any other way either because your GUI is frozen waiting for your actionPerformed to finish.

On a less critical issue, Thread.sleep is a static method so you shouldn't be calling it on a Thread instance. It's not really wrong, but it's confusing since sleep always causes the current thread to sleep and someone might think that you can use it to make some other thread sleep.

Hi,
Using the above code I posted, could you please seperate the infinite thread from the main thread so that my program works properly?
The start button needs to start the infinite thread, and stop button needs to stop it. The code inside the thread is the same as above.
Many thanks

Well, you could put a System.exit(0); after you exit from the infinite loop...
Say, for example, that you have a Thread class as mentioned above:

new Thread(new Runnable(){
    @SuppressWarnings("static-access")
    public void run(){
        int i=0;
        while(stp){
            captureScreenShot(".", "jpg", "pic"+Integer.toString(i++)+".jpg");
            try {
                Thread.currentThread().sleep(2000);
            } catch (InterruptedException e) {
                //error handling if needed
            }
        }
        System.exit(0); //here you exit
    }
}).start();

And I would make it easier by just putting this in the constructor, for example, if you make your class ScreenShotRobot extend JFrame...

public class ScreenShotRobot extends JFrame {
    private JButton stp = new JButton ("Stop");
    private volatile boolean loop_status = true;
    //other data

    public ScreenShotRobot{
        stop.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                loop_status = false;
            }
        });
    }
    add(stop);
    new Thread(new Runnable(){
        @SuppressWarnings("static-access")
        public void run(){
            int i=0;
            while(loop_status){
            captureScreenShot(".", "jpg", "pic"+Integer.toString(i++)+".jpg");
            try {
                Thread.currentThread().sleep(2000);
            } catch (InterruptedException e) {
            }
        }
        System.exit(0);
    }
    }).start();

    //insert your functions here... e.g. your captureScreenShot implementation

    public static void main(String arg[]){
        ScreenShotRobot ssr = new ScreenShotRobot();
        ssr.pack();
        ssr.setVisible(true);
    }
}

Or you could put them in another function, say init and than call it...

This question has already been answered. Start a new discussion instead.