使用JavaFX创建托盘图标

时间:2016-11-13 06:24:34

标签: java javafx trayicon

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

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

enter image description here

5 个答案:

答案 0 :(得分:10)

如果要相信this,JavaFX将在未来的更新中使用托盘图标。然后坚持AWT。使用JDK错误系统上的this thread跟踪开发情况。希望这会有所帮助。

答案 1 :(得分:3)

您不能使用纯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

答案 2 :(得分:2)

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

原始文档链接: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.");
    }

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

System tray program example

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

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

答案 3 :(得分:2)

如果您不想直接使用AWT,我创建了一个小项目FXTrayIcon,该项目将JavaFX MenuItems转换为AWT MenuItems,并提取了所有难看的AWT位。直到JavaFX本地支持,这至少是一个小帮助。

my GitHub page上查看

答案 4 :(得分:0)

我做到了。带有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);
}
}