java 使用 JavaFX 创建托盘图标

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40571199/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 05:20:01  来源:igfitidea点击:

Creating tray icon using JavaFX

javajavafxtrayicon

提问by sappy

I want to write a tray icon via JavaFx, but I only find that can write by awt. Is there any way that can write it use JavaFx?

我想通过 写一个托盘图标JavaFx,但我发现只能通过awt. 有什么方法可以写它使用JavaFx吗?

It will look like these tray icons from Windows 10:

它看起来像 Windows 10 中的这些托盘图标:

enter image description here

在此处输入图片说明

回答by Ayaskant Mishra

If thisis to be believed, JavaFX will feature tray icons in a future update. Till then stick to AWT. Keep track of the development using this threadon the JDK bug system. Hope this helps.

如果是可信的,JavaFX 将在未来的更新中提供托盘图标。直到然后坚持AWT。在 JDK 错误系统上使用此线程跟踪开发。希望这可以帮助。

回答by Sergey Gornostaev

You can't with pure JavaFX, but you can use AWT with JavaFX:

您不能使用纯 JavaFX,但可以将 AWT 与 JavaFX 一起使用:

import javafx.application.*;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.*;

import javax.imageio.ImageIO;
import java.io.IOException;
import java.net.URL;
import java.text.*;
import java.util.*;

// Java 8 code
public class JavaFXTrayIconSample extends Application {

    // one icon location is shared between the application tray icon and task bar icon.
    // you could also use multiple icons to allow for clean display of tray icons on hi-dpi devices.
    private static final String iconImageLoc =
            "http://icons.iconarchive.com/icons/scafer31000/bubble-circle-3/16/GameCenter-icon.png";

    // application stage is stored so that it can be shown and hidden based on system tray icon operations.
    private Stage stage;

    // a timer allowing the tray icon to provide a periodic notification event.
    private Timer notificationTimer = new Timer();

    // format used to display the current time in a tray icon notification.
    private DateFormat timeFormat = SimpleDateFormat.getTimeInstance();

    // sets up the javafx application.
    // a tray icon is setup for the icon, but the main stage remains invisible until the user
    // interacts with the tray icon.
    @Override public void start(final Stage stage) {
        // stores a reference to the stage.
        this.stage = stage;

        // instructs the javafx system not to exit implicitly when the last application window is shut.
        Platform.setImplicitExit(false);

        // sets up the tray icon (using awt code run on the swing thread).
        javax.swing.SwingUtilities.invokeLater(this::addAppToTray);

        // out stage will be translucent, so give it a transparent style.
        stage.initStyle(StageStyle.TRANSPARENT);

        // create the layout for the javafx stage.
        StackPane layout = new StackPane(createContent());
        layout.setStyle(
                "-fx-background-color: rgba(255, 255, 255, 0.5);"
        );
        layout.setPrefSize(300, 200);

        // this dummy app just hides itself when the app screen is clicked.
        // a real app might have some interactive UI and a separate icon which hides the app window.
        layout.setOnMouseClicked(event -> stage.hide());

        // a scene with a transparent fill is necessary to implement the translucent app window.
        Scene scene = new Scene(layout);
        scene.setFill(Color.TRANSPARENT);

        stage.setScene(scene);
    }

    /**
     * For this dummy app, the (JavaFX scenegraph) content, just says "hello, world".
     * A real app, might load an FXML or something like that.
     *
     * @return the main window application content.
     */
    private Node createContent() {
        Label hello = new Label("hello, world");
        hello.setStyle("-fx-font-size: 40px; -fx-text-fill: forestgreen;");
        Label instructions = new Label("(click to hide)");
        instructions.setStyle("-fx-font-size: 12px; -fx-text-fill: orange;");

        VBox content = new VBox(10, hello, instructions);
        content.setAlignment(Pos.CENTER);

        return content;
    }

    /**
     * Sets up a system tray icon for the application.
     */
    private void addAppToTray() {
        try {
            // ensure awt toolkit is initialized.
            java.awt.Toolkit.getDefaultToolkit();

            // app requires system tray support, just exit if there is no support.
            if (!java.awt.SystemTray.isSupported()) {
                System.out.println("No system tray support, application exiting.");
                Platform.exit();
            }

            // set up a system tray icon.
            java.awt.SystemTray tray = java.awt.SystemTray.getSystemTray();
            URL imageLoc = new URL(
                    iconImageLoc
            );
            java.awt.Image image = ImageIO.read(imageLoc);
            java.awt.TrayIcon trayIcon = new java.awt.TrayIcon(image);

            // if the user double-clicks on the tray icon, show the main app stage.
            trayIcon.addActionListener(event -> Platform.runLater(this::showStage));

            // if the user selects the default menu item (which includes the app name),
            // show the main app stage.
            java.awt.MenuItem openItem = new java.awt.MenuItem("hello, world");
            openItem.addActionListener(event -> Platform.runLater(this::showStage));

            // the convention for tray icons seems to be to set the default icon for opening
            // the application stage in a bold font.
            java.awt.Font defaultFont = java.awt.Font.decode(null);
            java.awt.Font boldFont = defaultFont.deriveFont(java.awt.Font.BOLD);
            openItem.setFont(boldFont);

            // to really exit the application, the user must go to the system tray icon
            // and select the exit option, this will shutdown JavaFX and remove the
            // tray icon (removing the tray icon will also shut down AWT).
            java.awt.MenuItem exitItem = new java.awt.MenuItem("Exit");
            exitItem.addActionListener(event -> {
                notificationTimer.cancel();
                Platform.exit();
                tray.remove(trayIcon);
            });

            // setup the popup menu for the application.
            final java.awt.PopupMenu popup = new java.awt.PopupMenu();
            popup.add(openItem);
            popup.addSeparator();
            popup.add(exitItem);
            trayIcon.setPopupMenu(popup);

            // create a timer which periodically displays a notification message.
            notificationTimer.schedule(
                    new TimerTask() {
                        @Override
                        public void run() {
                            javax.swing.SwingUtilities.invokeLater(() ->
                                trayIcon.displayMessage(
                                        "hello",
                                        "The time is now " + timeFormat.format(new Date()),
                                        java.awt.TrayIcon.MessageType.INFO
                                )
                            );
                        }
                    },
                    5_000,
                    60_000
            );

            // add the application tray icon to the system tray.
            tray.add(trayIcon);
        } catch (java.awt.AWTException | IOException e) {
            System.out.println("Unable to init system tray");
            e.printStackTrace();
        }
    }

    /**
     * Shows the application stage and ensures that it is brought ot the front of all stages.
     */
    private void showStage() {
        if (stage != null) {
            stage.show();
            stage.toFront();
        }
    }

    public static void main(String[] args) throws IOException, java.awt.AWTException {
        // Just launches the JavaFX application.
        // Due to way the application is coded, the application will remain running
        // until the user selects the Exit menu option from the tray icon.
        launch(args);
    }
}

code source

代码源

回答by Aupr

To make a system tray try following code:

要制作系统托盘,请尝试以下代码:

Original document link: https://docs.oracle.com/javase/tutorial/uiswing/misc/systemtray.html

原始文档链接:https: //docs.oracle.com/javase/tutorial/uiswing/misc/systemtray.html

    //Check the SystemTray is supported
    if (!SystemTray.isSupported()) {
        System.out.println("SystemTray is not supported");
        return;
    }
    final PopupMenu popup = new PopupMenu();

    URL url = System.class.getResource("/images/new.png");
    Image image = Toolkit.getDefaultToolkit().getImage(url);

    final TrayIcon trayIcon = new TrayIcon(image);

    final SystemTray tray = SystemTray.getSystemTray();

    // Create a pop-up menu components
    MenuItem aboutItem = new MenuItem("About");
    CheckboxMenuItem cb1 = new CheckboxMenuItem("Set auto size");
    CheckboxMenuItem cb2 = new CheckboxMenuItem("Set tooltip");
    Menu displayMenu = new Menu("Display");
    MenuItem errorItem = new MenuItem("Error");
    MenuItem warningItem = new MenuItem("Warning");
    MenuItem infoItem = new MenuItem("Info");
    MenuItem noneItem = new MenuItem("None");
    MenuItem exitItem = new MenuItem("Exit");

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

    trayIcon.setPopupMenu(popup);

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

Example system tray image in Windows 10

Windows 10 中的示例系统托盘图像

System tray program example

系统托盘程序示例

To invoke method of Javafx from awt event handler you may follw the following way:

要从 awt 事件处理程序调用 Javafx 的方法,您可以按照以下方式:

yourAwtObject.addActionListener(e -> {
    Platform.runLater(() -> primaryStage.show());
});

回答by algorithm

i made it. JavaFX with AWT. I have one example of a application that shows and hides when you make left clic. i really hope works for you

我做到了。带有 AWT 的 JavaFX。我有一个应用程序示例,它在您点击左键时显示和隐藏。我真的希望对你有用

import java.awt.AWTException;
import java.awt.Image;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.URL;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class MainApp2 extends Application {

int stateWindow = 1;

@Override
public void start(final Stage stage) throws Exception {

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

    URL url = System.class.getResource("/image/yourImage.png");
    Image image = Toolkit.getDefaultToolkit().getImage(url);

    //image dimensions must be 16x16 on windows, works for me
    final TrayIcon trayIcon = new TrayIcon(image, "application name");

    final SystemTray tray = SystemTray.getSystemTray();

    //Listener left clic XD
    trayIcon.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent event) {
            if (event.getButton() == MouseEvent.BUTTON1) {
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        if (stateWindow == 1) {
                            stage.hide();
                            stateWindow = 0;
                        } else if (stateWindow == 0) {
                            stage.show();
                            stateWindow = 1;
                        }
                    }
                });
            }

        }
    });

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

    stage.setTitle("Hello man!");
    Button btn = new Button();
    btn.setText("Say 'Hello man'");
    btn.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            System.out.println("Hello man!");
        }
    });
    StackPane root = new StackPane();
    root.getChildren().add(btn);
    stage.setScene(new Scene(root, 300, 250));
    Platform.setImplicitExit(false);
    stage.show();

}

/**
 * The main() method is ignored in correctly deployed JavaFX application.
 * main() serves only as fallback in case the application can not be
 * launched through deployment artifacts, e.g., in IDEs with limited FX
 * support. NetBeans ignores main().
 *
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}
}