【发布时间】:2020-11-19 03:41:04
【问题描述】:
我希望我的程序从系统托盘菜单执行屏幕截图。
我让它工作了,但 MenuItem 本身隐藏得不够快,并且与屏幕的其余部分一起被捕获。
这是一个 MCVE,基于 Java 教程的 TrayIconDemo 示例的精简版本: (编辑:感谢 Holger 的评论,使之变得更加简单)
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class TrayCapture {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
createAndShowGUI();
}
catch (Exception e) {
e.printStackTrace();
}
}
});
}
private static void createAndShowGUI() throws Exception {
//Check the SystemTray support
if (!SystemTray.isSupported()) {
System.err.println("SystemTray is not supported");
return;
}
final PopupMenu popup = new PopupMenu();
final TrayIcon trayIcon = new TrayIcon(ImageIO.read(new URL("https://i.stack.imgur.com/wCF8S.png")));
trayIcon.setImageAutoSize(true);
// Create a popup menu components
MenuItem captureItem = new MenuItem("Capture");
MenuItem exitItem = new MenuItem("Exit");
//Add components to popup menu
popup.add(captureItem);
popup.add(exitItem);
trayIcon.setPopupMenu(popup);
SystemTray.getSystemTray().add(trayIcon);
captureItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
File outputFile = new File("capture.png");
ImageIO.write(new Robot().createScreenCapture(
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize())),
"png",
outputFile);
JOptionPane.showMessageDialog(null, "Screenshot saved to: " + outputFile.getAbsolutePath());
}
catch (AWTException | IOException ex) {
ex.printStackTrace();
}
}
});
exitItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
SystemTray.getSystemTray().remove(trayIcon);
System.exit(0);
}
});
}
}
这是一个结果捕获。
如您所见,PopupMenu 已关闭,但“Capture”MenuItem 在机器人进行捕获时仍然可见,并且是捕获图像的一部分。
有没有办法强制重绘以隐藏 MenuItem 或在它隐藏时收到通知,以便我可以确保机器人不会捡起它?我宁愿避免任意的 Thread.sleep() 因为它只是一个盲目的竞争条件......
KR, 维克内
【问题讨论】:
-
使用
SwingUtilities.invokeLater()将您的代码包装在您截取屏幕截图的位置。这将允许关闭弹出窗口。 -
菜单已关闭。您看到的是 Windows 自身为所选菜单项创建的淡出效果。当您仔细观察时,您会注意到所有托盘图标菜单都有这种效果,无论应用程序如何。我不知道有什么方法可以确定在您自己的应用程序之外执行的动画是否已经结束。附带说明一下,
createScreenCapture确实已经返回了BufferedImage,这会使您的一半代码过时,您只需要ImageIO.write(new Robot() .createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize())), "png", outputFile) -
看看this。 Windows 10 中也存在此设置。转到
Control Panel-->System and Security-->System然后 高级设置 或其他什么...我找到了路径,但我没有不知道英文是怎么翻译的。我知道,但这不会回答这个问题。我没有尝试过,但它可能会有所帮助。 -
@weisj:试过
invokeLater(),无济于事:-( -
@Holger:哦,Windows 动画,不错。我想睡觉是唯一的选择:-(。确实图像复制代码是多余的,不知道我在想什么。我修好了。谢谢
标签: java swing awt awtrobot system-tray