简体   繁体   English

Java 机器人从 Windows 系统托盘启动

[英]Java Robot launched from Windows System Tray

I'd like my program to perform a screen capture from a System Tray menu.我希望我的程序从系统托盘菜单执行屏幕捕获。

I got it to work, but the MenuItem itself does not hide fast enough and is captured along with the rest of the screen.我让它工作了,但是 MenuItem 本身隐藏得不够快,并且与屏幕的 rest 一起被捕获。

Here's a MCVE, based on a stripped down version of The Java Tutorial's TrayIconDemo sample: (Edit: made even more minimal thanks to Holger's comment)这是一个 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);
            }
        });
    }
}

And here is a resulting capture.这是一个结果捕获。

捕获包括菜单项

As you can see, the PopupMenu is closed but the "Capture" MenuItem was still visible when the Robot took the capture and is part of the captured image.如您所见,PopupMenu 已关闭,但“Capture”MenuItem 在机器人进行捕获时仍然可见,并且是捕获图像的一部分。

Is there a way to force a repaint to hide the MenuItem or get a notification when it's hidden so I can make sure the Robot will not pick it up?有没有办法强制重绘以隐藏 MenuItem 或在隐藏时收到通知,以便我可以确保机器人不会捡起它? I'd rather avoid an arbitrary Thread.sleep() because it's just a blind race condition...我宁愿避免任意的 Thread.sleep() 因为它只是一个盲目的竞争条件......

KR, Vicne KR,维克内

This is not an artifact of your Java application, as it is a Windows-specific animation of the selected menu item that continues while the popup menu is already closed.这不是您的 Java 应用程序的产物,因为它是所选菜单项的 Windows 特定 animation 在弹出菜单已关闭时继续。

As far as I know, there is no way to monitor the animation progress from the Java side (apart from capturing the screen and looking whether the artifact is still there).据我所知,没有办法从 Java 端监控 animation 进度(除了捕获屏幕并查看工件是否仍然存在)。

The best option is to have a configurable delay (with a reasonable default of, eg 300 ms) before doing the screenshots.最好的选择是在截屏之前有一个可配置的延迟(合理的默认值,例如 300 毫秒)。 All screenshot tools I know of, use a configurable delay anyway.我知道的所有屏幕截图工具,无论如何都使用可配置的延迟。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM