如何动态更改JavaFX中的托盘图标图像,如Dropbox托盘图标

时间:2014-11-08 05:01:56

标签: javafx javafx-2 awt javafx-8 trayicon

在Dropbox中,托盘图标会动态更改。 上传文件时,会显示同步图标。 当所有文件同步时,dropbox会显示其他图标(最新状态图标)。

https://mockupstogo.mybalsamiq.com/projects/icons/Dropbox

我想使用JavaFX

开发相同的功能

第一次通话时,trayIcon.setImage正常工作(显示蓝色托盘图标)。 但第二次调用,它不起作用(灰色托盘图标未显示)。 它只显示空框。

是JavaFX错误吗?

package application;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TreeView;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;


public class Main 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";

//private static final String iconImageLoc1 =
//  "http://icons.iconarchive.com/icons/icons-land/metro-halloween/96/Cauldron-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();


private TreeView<String> treeView;

// 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
        );

        URL imageLoc1 = new URL(
                iconImageLoc1
        );
        java.awt.Image image = ImageIO.read(imageLoc);

        java.awt.Image image1 = ImageIO.read(imageLoc1);*/


        Dimension size = tray.getTrayIconSize();
        BufferedImage bi = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB);
        Graphics g = bi.getGraphics();

        g.setColor(java.awt.Color.BLUE);
        g.fillRect(0, 0, size.width, size.height);

        System.out.println(size.width);
        System.out.println(size.height);
        java.awt.TrayIcon trayIcon = new java.awt.TrayIcon(bi);


        // 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
                            )
                        );

                        System.out.println(size.width);
                        System.out.println(size.height);
                        BufferedImage bi = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB);
                        Graphics g = bi.getGraphics();

                        g.fillRect(0, 0, size.width, size.height);
                        g.setColor(java.awt.Color.GRAY);

                        trayIcon.setImage(bi);

                    }
                },
                5_000,
                60_000
        );

        // add the application tray icon to the system tray.
        tray.add(trayIcon);

        //trayIcon.setImage(image1);
    //} catch (java.awt.AWTException | IOException e) {
    } catch (java.awt.AWTException 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);
}
}

1 个答案:

答案 0 :(得分:1)

我认为问题在于不同的图像尺寸,你改变了第一个尺寸的第二个图标!