1

I have written two classes, FullScreen, which contains the logic for the screenshot, and FullScreenGUI, which contains the logic for simulating the photo click effect.

The photo click effect is basically flashing the screen with white color for a short period of time, say 50ms after the screenshot is taken. It is produced by covering the whole screen by a JFrame with an opacity of 1%. The background is made white and then the opacity is changed from 1% to 100%, kept like that for 50ms, then back to 1%.

The FullScreen constructor takes two parameters, one for number of times to take screenshot, and the other for the duration in between.

The FullScreenGUI constructs a JFrame, maximises it, sets the background to white. When the fire() method is called, it changes the opacity as required to produce the effect.

The Question:

Using the code below I am able to produce the effect for the first time the screenshot is taken, but not for the subsequent clicks. Suppose, FullScreen constructor is called with the parameters (4,2) (i.e. to take 4 clicks each at 2 seconds duration), then the effect is produced nicely for the first click but not for the remaining 3 clicks. JFrame of the FullScreenGUI does not seem to come to front, so the effect is not visible. I have tried JFrame.setAlwaysOnTop(true), JFrame.toFront() but they don't seem to bring the JFrame to the top.

There is no problem in taking the screenshot, but instead with the effect. Do you have any other ideas to produce it ?

Here is the code: FullScreen.java

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.Timer;
import javax.swing.filechooser.FileSystemView;

class FullScreen
{   
    int times, duration;
    Timer t;
    Robot r;
    BufferedImage bi;
    FullScreenGUI fg;

FullScreen(int tim, int duration) 
{
    fg = new FullScreenGUI();
    fg.setVisible(true);
    this.times = tim;
    this.duration = duration;
    try {
        r = new Robot();
    } catch (AWTException e) {
        e.printStackTrace();
    }
    System.out.println("Inside constructor");
    t = new Timer(duration*1000, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {

            System.out.println("Inside action");
            if(times>0)
            {
                System.out.println("times: "+times);

                //Get the screenshot
                bi = capture();

                //Gives the path of the home directory. For windows, it'll go to your desktop
                FileSystemView filesys = FileSystemView.getFileSystemView();
                File fl = filesys.getHomeDirectory();
                saveImage(bi, fl);

                //Produces the "clicking" effect
                fg.setAlwaysOnTop(true);
                fg.toFront();
                fg.fire();

                times--;
            }
            else
                t.stop();
        }
    });
}

public void fire()
{
    t.start();
}

public void saveImage(BufferedImage source, File destination)
{
    System.out.println("Inside saveimage");
    if(destination.isDirectory())
    {
        System.out.println("destination: "+destination.getAbsolutePath());
        String tmp = destination.getAbsolutePath() + File.separator + "Screenshot";
        String str;
        int i=1;
        for(str=tmp; (new File(str+".png").exists()); i++)
        {
            str = tmp + "_" + String.valueOf(i);
            System.out.println("trying: "+str);
        }

        try {
            ImageIO.write(source, "png", new File(str+".png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public BufferedImage capture()
{
    System.out.println("Captured");
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    return r.createScreenCapture(new Rectangle(d));
}

public static void main(String arg[])
{
    //click 4 times each at an interval of 2 seconds
    FullScreen f = new FullScreen(4,2);

    f.fire();
    while(f.t.isRunning());
}
}

FullScreenGUI.java

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

class FullScreenGUI extends JFrame {

FullScreenGUI()
{
    setExtendedState(JFrame.MAXIMIZED_BOTH);
    setUndecorated(true);
    setResizable(false);
    setOpacity(0.01f);
    setAlwaysOnTop(true);

    setLayout(new BorderLayout());
    JLabel jl = new JLabel();
    jl.setBackground(Color.white);
    add(jl);        

    setDefaultCloseOperation(EXIT_ON_CLOSE);
}

public void fire()
{
    System.out.println("click");
    setVisible(true);

    try{

    setOpacity(1f);
    Thread.sleep(50);
    setOpacity(0.1f);

    }catch(Exception e) { e.printStackTrace(); }

    setVisible(false);
}

}
Divyanshu
  • 179
  • 7

1 Answers1

4

The source of the problem is Thread.sleep(50);.

Don't block the EDT (Event Dispatch Thread) - the GUI will 'freeze' when that happens. Instead of calling Thread.sleep(n) implement a Swing Timer for this task. See Concurrency in Swing for more details.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 1
    .-), I sure that EDT must be freezed, please see linked post in my deleted post, Swing Timer is contraproductive, Merry Christmast to your easiest corner of the world – mKorbel Dec 24 '12 at 11:43
  • Isn't Christmas tomorrow guys? :P right now its 24/12/2012 04:44PM CAT. – David Kroukamp Dec 24 '12 at 14:44
  • 1
    @DavidKroukamp It's been Christmas for the last 1h45m here (Sydney). The rest of the world should catch up! – Andrew Thompson Dec 24 '12 at 14:45
  • @AndrewThompson Haha I though timezones would clash :) merry Christmas (and previously +1 for great answer) wish I could do it again for answering on christmas :P – David Kroukamp Dec 24 '12 at 14:46