I'm trying to emulate Objective C's NSStatusItem functionality in Java. That is, I'm trying to write a Java app that will sit in the Mac's menubar, like this. Here's a link to Apple's documentation on StatusBar.
Any way to do this in Java?
Use java.awt.SystemTray. I've confirmed it works on OS X Lion. According to this question, it's also possible to do with SWT.
Example:
import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
public class MenuBarIconTest {
public static void main(String[] args) throws MalformedURLException {
TrayIcon trayIcon = null;
if (SystemTray.isSupported()) {
// get the SystemTray instance
SystemTray tray = SystemTray.getSystemTray();
// load an image
Image image = Toolkit.getDefaultToolkit().getImage(new URL("http://cdn1.iconfinder.com/data/icons/Hypic_Icon_Pack_by_shlyapnikova/16/forum_16.png"));
// create a action listener to listen for default action executed on the tray icon
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("action");
// execute default action of the application
// ...
}
};
// create a popup menu
PopupMenu popup = new PopupMenu();
// create menu item for the default action
MenuItem defaultItem = new MenuItem("Do the action");
defaultItem.addActionListener(listener);
popup.add(defaultItem);
/// ... add other items
// construct a TrayIcon
trayIcon = new TrayIcon(image, "Tray Demo", popup);
// set the TrayIcon properties
trayIcon.addActionListener(listener);
// ...
// add the tray image
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.err.println(e);
}
// ...
} else {
// disable tray option in your application or
// perform other actions
//...
}
// ...
// some time later
// the application state has changed - update the image
if (trayIcon != null) {
//trayIcon.setImage(updatedImage);
}
}
}
There is a NICE library for doing this ... best one I've seen that integrates the SWIFT ability for menubar access with JavaFX ... since FX has no native way to work out of the menubar.
Here is the link if you're interested.
Related
I'm creating a cross-platform Java app with options available through a system tray menu. Unfortunately, any sub-menus I put in this menu cannot be opened when navigating via keyboard on Mac. Once I get to the sub-menu and I hit the return key or space bar, the whole menu closes instead of opening the sub-menu.
Via keyboard (before hitting the space bar or return key):
Via mouse (after hovering over the menu):
Interestingly, clicking on the sub-menu also closes the whole menu.
Here's my Main.java code:
import java.awt.AWTException;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.Toolkit;
import java.awt.Image;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.util.*;
public class Main {
public static void main(String[] args) {
if(!SystemTray.isSupported()) {
System.err.println("System tray feature is not supported");
return;
}
try {
BufferedImage img = ImageIO.read(Main.class.getResource("tray_icon_mac.png"));
TrayIcon trayIcon = new TrayIcon(img, "Test Icon", null);
trayIcon.setImageAutoSize(true);
final SystemTray tray = SystemTray.getSystemTray();
try {
tray.add(trayIcon);
PopupMenu rootMenu = new PopupMenu();
MenuItem about = new MenuItem("About");
rootMenu.add(about);
Menu options = new Menu("Options");
MenuItem option1 = new MenuItem("Option 1");
options.add(option1);
rootMenu.add(options);
trayIcon.setPopupMenu(rootMenu);
}
catch (AWTException e) {
System.out.println("TrayIcon could not be added.");
return;
}
}
catch(IOException e) {
System.out.println(e);
return;
}
}
}
Any insight on this would be greatly appreciated!
Edit: I found out that you can navigate to the sub-menu using the right arrow key. However, regular sub-menus allow opening sub-menus using either the right arrow key, space bar, or return key. So while it is possible to open, there are fewer options for opening it.
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?
It will look like these tray icons from Windows 10:
If this is to be believed, JavaFX will feature tray icons in a future update. Till then stick to AWT. Keep track of the development using this thread on the JDK bug system. Hope this helps.
If you'd prefer to not use AWT directly, I've created a small project FXTrayIcon which translates JavaFX MenuItems to AWT MenuItems and abstracts away all of the ugly AWT bits. It's at least a small help until JavaFX supports this natively.
See it on my GitHub page
You can't with pure JavaFX, but you can use AWT with 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
To make a system tray try following code:
Original document link: 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
To invoke method of Javafx from awt event handler you may follw the following way:
yourAwtObject.addActionListener(e -> {
Platform.runLater(() -> primaryStage.show());
});
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
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);
}
}
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?
It will look like these tray icons from Windows 10:
If this is to be believed, JavaFX will feature tray icons in a future update. Till then stick to AWT. Keep track of the development using this thread on the JDK bug system. Hope this helps.
If you'd prefer to not use AWT directly, I've created a small project FXTrayIcon which translates JavaFX MenuItems to AWT MenuItems and abstracts away all of the ugly AWT bits. It's at least a small help until JavaFX supports this natively.
See it on my GitHub page
You can't with pure JavaFX, but you can use AWT with 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
To make a system tray try following code:
Original document link: 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
To invoke method of Javafx from awt event handler you may follw the following way:
yourAwtObject.addActionListener(e -> {
Platform.runLater(() -> primaryStage.show());
});
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
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);
}
}
With Java, you can use TrayIcon and java.awt.SystemTray to make a trayicon. But this icon looks bad when you use for example Windows in combination with a 4K monitor and Windows is automatically scaling everything bigger.
Java sets the trayiconsize to 16x16 but this is way too small for the scaled mode and therefore it looks bad. Do you know how to fix this?
Edit:
Here is an example code and screenshot of the result. I am using BMW's logo (256x256 pixel) :)
package trayicon;
import java.awt.AWTException;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Trayicon {
public static void main(String[] args) throws IOException {
//Check the SystemTray is supported
if (!SystemTray.isSupported()) {
System.out.println("SystemTray is not supported");
return;
}
BufferedImage img = ImageIO.read(new File("256x256.png"));
final TrayIcon trayIcon =
new TrayIcon(img, "Trayicon");
trayIcon.setImageAutoSize(true);
final SystemTray tray = SystemTray.getSystemTray();
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.out.println("TrayIcon could not be added.");
}
System.in.read();
System.exit(0);
}
}
Result (look at the lower right icon):
Search doesn't turn anything up for this problem.
I'm using simple code to display a JFileChooser dialog with customized title and accept button:
JFileChooser fc = new JFileChooser();
fc.showDialog(null,"MyText");
On Windows 7 this works as expected: a Save Dialog is displayed, with "Save" replaced by "MyText" on the Accept button and dialog title.
However, on Mac OS X, only the Accept button text is changed - the dialog title is blank. I'm using Java SE 7 and MacOS 10.8.5.
By inserting this line between the two above:
fc.setDialogTitle("MyText");
The correct title is displayed. Is this a known issue, and/or can anyone else reproduce this behavior?
What you experience on Windows is not the expected behaviour (as it is not documented), it is just an implementation side effect.
The showDialog() is used to display a custom dialog (e.g. not an Open nor Save dialog). It has a parameter to specify the text of the Approve button. If the title has not been set with the setDialogTitle() method, the implementation arbitrarily chooses to use the approve button's text as the title on Windows OS, however this is not documented anywhere and you should not count on this to work.
If you want a custom title, use setDialogTitle(). If you want a custom approve button text, use setApproveButtonText(). Obviously showDialog() also takes the approve button's text in which case you do not need to call setApproveButtonText() prior.
If you want an Open dialog, use the showOpenDialog() method. If you want a Save dialog, use the showSaveDialog(). Only use showDialog() if you want a custom dialog.
here are all accesible keys for UIManager (part of them aren't accessible by looping in UIManager, for all supported Native OS's and standard LaFs), with notice that success is volatille, depends of Native OS and used LaF
you can to get parent from JFileChooser, to cast to JDialog
add JFileChooser to your own JDialog (simple without any special settings, e.g. myDialog.add(myFileChooser); + myDialog.pack();)
there is possible to play with components tree
all accesible keys for UIManager (part of them ....
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Locale;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class Test extends JDialog {
private JFileChooser fc = null;
private JFrame bfcParent = null;
public Test(JFrame parent, boolean modal) {
super(parent, modal);
this.bfcParent = parent;
if (fc == null) {
fc = new JFileChooser();
fc.setAcceptAllFileFilterUsed(false);
fc.setLocale(Locale.ENGLISH);
UIManager.put("FileChooser.openDialogTitleText", "Open Dialog");
UIManager.put("FileChooser.saveDialogTitleText", "Save Dialog");
UIManager.put("FileChooser.lookInLabelText", "LookIn");
UIManager.put("FileChooser.saveInLabelText", "SaveIn");
UIManager.put("FileChooser.upFolderToolTipText", "UpFolder");
UIManager.put("FileChooser.homeFolderToolTipText", "HomeFolder");
UIManager.put("FileChooser.newFolderToolTipText", "New FOlder");
UIManager.put("FileChooser.listViewButtonToolTipText", "View");
UIManager.put("FileChooser.detailsViewButtonToolTipText", "Details");
UIManager.put("FileChooser.fileNameHeaderText", "Name");
UIManager.put("FileChooser.fileSizeHeaderText", "Size");
UIManager.put("FileChooser.fileTypeHeaderText", "Type");
UIManager.put("FileChooser.fileDateHeaderText", "Date");
UIManager.put("FileChooser.fileAttrHeaderText", "Attr");
UIManager.put("FileChooser.fileNameLabelText", "Label");
UIManager.put("FileChooser.filesOfTypeLabelText", "filesOfType");
UIManager.put("FileChooser.openButtonText", "Open");
UIManager.put("FileChooser.openButtonToolTipText", "Open");
UIManager.put("FileChooser.saveButtonText", "Save");
UIManager.put("FileChooser.saveButtonToolTipText", "Save");
UIManager.put("FileChooser.directoryOpenButtonText", "Open Directory");
UIManager.put("FileChooser.directoryOpenButtonToolTipText", "Open Directory");
UIManager.put("FileChooser.cancelButtonText", "Cancel");
UIManager.put("FileChooser.cancelButtonToolTipText", "CanMMcel");
UIManager.put("FileChooser.newFolderErrorText", "newFolder");
UIManager.put("FileChooser.acceptAllFileFilterText", "Accept");
fc.updateUI();
SwingUtilities.updateComponentTreeUI(fc);
}
}
public int openFileChooser() {
//fc.setDialogTitle("Load File);
fc.resetChoosableFileFilters();
int returnVal = 0;
fc.setDialogType(JFileChooser.OPEN_DIALOG);
returnVal = fc.showDialog(this.bfcParent, "Load File");
if (returnVal == JFileChooser.APPROVE_OPTION) { //Process the results.
System.out.println("Opened");
} else {
System.out.println("Failed");
}
return returnVal;
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("FileChooser");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel jp = new JPanel(new BorderLayout());
JButton openButton = new JButton("Open File");
final Test test = new Test(frame, true);
openButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
test.openFileChooser();
}
});
openButton.setEnabled(true);
jp.add(openButton, BorderLayout.AFTER_LAST_LINE);
frame.add(jp); //Add content to the window.
frame.pack();//Display the window.
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//Turn off metal's use of bold fonts
createAndShowGUI();
}
});
}
}