我写了两个类,FullScreen
,其中包含截图的逻辑,和FullScreenGUI
,其中包含模拟照片点击效果的逻辑。
照片点击效果基本上是在屏幕上短暂闪烁白色,比如截图后50ms。它是通过不透明度为1%的JFrame
覆盖整个屏幕产生的。背景变成白色,然后不透明度从1%变为100%,保持50ms,然后恢复到1%。
FullScreen
构造函数接受两个参数,一个用于截图的次数,另一个用于两者之间的持续时间。
FullScreenGUI
构造一个JFrame
,最大化它,将背景设置为白色。当调用fire()
方法时,它会根据需要更改不透明度以产生效果。
问题:
使用下面的代码,我能够在第一次截屏时产生效果,但不能用于随后的点击。假设FullScreen
构造函数使用参数(4,2)
调用(即在2秒的持续时间内每次点击4次),那么第一次点击的效果很好,但剩余的3次点击没有。FullScreenGUI
的JFrame
似乎没有出现在前面,因此效果不可见。我尝试过JFrame. setAlwaysOnTop(true)
,JFrame.toFront()
,但它们似乎没有将JFrame
带到顶部。
截图没有问题,反而有了效果,大家有没有其他的想法来制作呢?
下面是代码: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);
}
}
问题的来源是Thread.睡眠(50);
。
不要阻塞EDT(事件调度线程)-当这种情况发生时,GUI将“冻结”。而不是调用Thread.睡眠(n)
为此任务实现SwingTimer
。有关详细信息,请参阅Swing中的并发。