繁体   English   中英

仅在Java中没有停靠/任务栏图标的系统托盘中运行

[英]Run only in system tray with no dock/taskbar icon in Java

是否有可能Java应用程序(精确的.jar只能在SystemTray运行,而用户不会在任务栏/ Dock上看到任何内容,而是拥有像JWindow这样的可见组件?
一个例子是Dropbox的MacOS应用程序,它在SystemTray显示以下窗口,同时码头上仍然没有可见图标。

如果是这样,那怎么办呢?

是的,可以做到。 下面是一些示例代码,它将菜单添加到托盘图标,并将监听器添加到该菜单中的菜单项,该菜单项创建了一个用户单击该项目的对话框。 当我使用此代码创建一个可运行的jar时,它不会在任务栏上显示图标,它只显示系统托盘中的图标。

import java.awt.AWTException;
import java.awt.Image;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JOptionPane;

public class SystemTrayExample {
    private static final SystemTray tray = SystemTray.getSystemTray();
    private static final PopupMenu popup = new PopupMenu();
    private static TrayIcon trayIcon;

    public static void main(String[] args) {

        if (!SystemTray.isSupported()) {
            // SystemTray is not supported
        }

        trayIcon = new TrayIcon(createImage("icon.jpg", "tray icon"));
        trayIcon.setImageAutoSize(true);

        ActionListener listener = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                MenuItem item = (MenuItem) e.getSource();

                String s = (String) JOptionPane.showInputDialog(null, "Report "
                        + item.getLabel(), "Create Report",
                        JOptionPane.PLAIN_MESSAGE, null, null, "");

                // Do something with the string...
            }
        };
        MenuItem exitItem = new MenuItem("Exit");
        exitItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                tray.remove(trayIcon);
                System.exit(0);
            }
        });


        Menu reportMenu = new Menu("Report");
        MenuItem menuItem = new MenuItem("Item");
        reportMenu.add(menuItem);
        menuItem.addActionListener(listener);
        popup.add(reportMenu);
        popup.add(exitItem);
        trayIcon.setPopupMenu(popup);

        try {
            tray.add(trayIcon);
        } catch (AWTException e) {
            // TrayIcon could not be added
        }

    }

    // Obtain the image URL
    protected static Image createImage(String path, String description) {
        URL imageURL = SystemTrayExample.class.getResource(path);

        if (imageURL == null) {
            System.err.println("Resource not found: " + path);
            return null;
        } else {
            return (new ImageIcon(imageURL, description)).getImage();
        }
    }
}

当然可以做到(对于Windows无论如何)。 这是一个带弹出菜单的可运行示例。 托盘中显示的图标是从URL中检索的(使用您想要的任何图标:

import java.awt.AWTException;
import java.awt.CheckboxMenuItem;
import java.awt.Image;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;


public class TrayIconDemo2 {

    public TrayIconDemo2() throws Exception {
        initComponents();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    new TrayIconDemo2();
                } catch (Exception ex) { System.out.println("Error - " + ex.getMessage()); }
            }
        });
    }

    private void initComponents() throws Exception {
        createAndShowTray();
    }

    private void createAndShowTray() throws Exception {
        //Check the SystemTray is supported
        if (!SystemTray.isSupported()) {
            System.out.println("SystemTray is not supported");
            return;
        }

        PopupMenu popup = new PopupMenu();
        //retrieve icon form url and scale it to 32 x 32
        final TrayIcon trayIcon = new TrayIcon(ImageIO.read(
                new URL("http://www.optical-illusions.com/thumb/ec665b8dfcc248da272224972e9eaf92.jpg"))
                .getScaledInstance(32, 32, Image.SCALE_SMOOTH), null);

        //get the system tray
        final SystemTray tray = SystemTray.getSystemTray();

        // Create a pop-up menu components
        MenuItem aboutItem = new MenuItem("About");
        aboutItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                JOptionPane.showMessageDialog(null, "About");
            }
        });

        final  CheckboxMenuItem cb1 = new CheckboxMenuItem("Show Tooltip");
        cb1.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent ie) {
                if(cb1.getState()==true) {
                trayIcon.setToolTip("Hello, world");
                }else {
                trayIcon.setToolTip("");
                }
            }
        });

        Menu displayMenu = new Menu("Display");

        MenuItem infoItem = new MenuItem("Info");
        //add actionlistner to Info menu item
        infoItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                JOptionPane.showMessageDialog(null, "Display Info of some sort :D");
            }
        });

        MenuItem exitItem = new MenuItem("Exit");
        //add actionlistner to Exit menu item
        exitItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                System.exit(0);
            }
        });

        //Add components to pop-up menu
        popup.add(aboutItem);
        popup.addSeparator();
        popup.add(cb1);
        popup.addSeparator();
        popup.add(displayMenu);
        displayMenu.add(infoItem);
        popup.add(exitItem);

        trayIcon.setPopupMenu(popup);

        try {
            tray.add(trayIcon);
        } catch (AWTException e) {
            System.out.println("TrayIcon could not be added.");
        }
    }
}

您可以从系统托盘图标中显示任何您喜欢的内容,但您应该通过弹出菜单进行显示。

把这一行:

System.setProperty("apple.awt.UIElement", "true");

作为主要内容的第一个陈述:

public static void main(String[] args) {
    System.setProperty("apple.awt.UIElement", "true");
    // Your stuff...
}

我已成功通过@DevilsHnd的“TrayIconDemo2”示例尝试了它,您可以在此页面中找到另一个答案。


顺便说一句,我会添加更多东西给@Muhammad Usman的答案 我已经粘贴了我在下面检查过的所有答案:

根据JavaFX,您无法在JavaFX应用程序中隐藏停靠图标。 请查看此链接

隐藏停靠图标有两种方法。

  • Apple标准方式,只需修改* .app / Contents / Info.plist并添加<key>LSUIElement</key> <string>1</string>
  • 以AWT应用程序启动应用程序并使用系统属性隐藏停靠图标。 设置系统属性调用后,JavaFX主方法和JavaFX应用程序将立即接管,没有停靠图标。 请参阅下面的示例代码段。

 /** - This class is intended to start application as AWT application before initializing - JavaFX application. JavaFX does not support dock-icon-less application so we are - creating JavaFX application from AWT application so that we can achieve the desired - functionality. - */ public class AWTMain { public static void main(String[] args) { // This is awt property which enables dock-icon-less // applications System.setProperty("apple.awt.UIElement", "true"); java.awt.Toolkit.getDefaultToolkit(); // This is a call to JavaFX application main method. // From now on we are transferring control to FX application. FXMain.main(args); } } 

这里FXMain被称为主类方法的前一类。

如果你正在使用maven和其他地方,你也需要修改.pom文件,你提到应用程序的主类。

暂无
暂无

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

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