In Windows 10 there is a notification that opens in the bottom right of the screen and I find them quite useful.
Is there is any way to create Windows notifications in Java? This is what they look like:
I can successfully produce this result using this very simple sample code:
import java.awt.*;
import java.awt.TrayIcon.MessageType;
public class TrayIconDemo {
public static void main(String[] args) throws AWTException {
if (SystemTray.isSupported()) {
TrayIconDemo td = new TrayIconDemo();
td.displayTray();
} else {
System.err.println("System tray not supported!");
}
}
public void displayTray() throws AWTException {
//Obtain only one instance of the SystemTray object
SystemTray tray = SystemTray.getSystemTray();
//If the icon is a file
Image image = Toolkit.getDefaultToolkit().createImage("icon.png");
//Alternative (if the icon is on the classpath):
//Image image = Toolkit.getDefaultToolkit().createImage(getClass().getResource("icon.png"));
TrayIcon trayIcon = new TrayIcon(image, "Tray Demo");
//Let the system resize the image if needed
trayIcon.setImageAutoSize(true);
//Set tooltip text for the tray icon
trayIcon.setToolTip("System tray icon demo");
tray.add(trayIcon);
trayIcon.displayMessage("Hello, World", "notification demo", MessageType.INFO);
}
}
This can be achieved with the SystemTray and TrayIcon classes. Also, if this is a new API for you, you might want to check the dedicated tutorial "How to Use the System Tray".
you can use Notifications with javafx easily with Notification class
java.lang.Object
org.controlsfx.control.Notifications
public static showNotification(String title,String text){
Notifications notificationTest=Notifications.create();
notificationTest.position(Pos.BASELINE_RIGHT);
notificationTest.title(title);
notificationTest.text(text);
notificationTest.show();//for error noti notificationTest.showError();
}
https://www.javadoc.io/static/org.controlsfx/controlsfx/8.40.16/org/controlsfx/control/Notifications.html
Related
I made a Windows 10 notification using the Eclipse IDE. I can't seem to get rid of the "OpenJDK Platform Binary" which shows whenever the notification pops up. I tried "MessageType.NONE" but it's still there.
Note: I can only solve this problem using Java.
import java.awt.*;
import java.awt.TrayIcon.MessageType;
public class notif {
public static void main(String[] args) throws AWTException {
notif td = new notif();
td.notifDisplay();
}
public void notifDisplay() throws AWTException {
SystemTray tray = SystemTray.getSystemTray();
Image img = Toolkit.getDefaultToolkit().createImage("icon.png");
TrayIcon trayIcon = new TrayIcon(img, "pepsi");
trayIcon.setImageAutoSize(true);
trayIcon.setToolTip("pepsi");
tray.add(trayIcon);
trayIcon.displayMessage("we are out of pepsi", ":(", MessageType.NONE);
}
}
On Mac OS, applications that run in the background sometimes have their icon attached to a gui or menu in the right corner of the screen. I believe it is similar to what Windows has on the bottom-right corner.
However I want this for my JavaFX application as well. And I don't know how to google for that. All I found was JavaFX' MenuBar, what unfortunately is not what I'm looking for.
You need to set a system property in order to move it out from your JFrame:
System.setProperty("apple.laf.useScreenMenuBar", "true");
This will show your JMenuBar in the MacOS Toolbar.
Or you could check if you are running MacOS and then set the property:
if (System.getProperty("os.name").contains("Mac")) {
System.setProperty("apple.laf.useScreenMenuBar", "true");
}
public class SystemTray {
private static final Logger logger = LogManager.getLogger(Main.class);
public static java.awt.SystemTray tray = java.awt.SystemTray.getSystemTray(); // set up a system tray icon.
public static TrayIcon trayIcon;
public static Image trayIconImage;
public static MenuItem startRecording;
public static MenuItem stopRecording;
public static MenuItem playRecording;
public static MenuItem pauseRecording;
public static MenuItem startOver;
public static MenuItem exitItem;
final static PopupMenu popup=new PopupMenu();
public static boolean windows = Main.checkOS();
public SystemTray() {
}
public static void addAppToTray() {
try {
// ensure awt toolkit is initialized.
Toolkit.getDefaultToolkit();
URL IconPath;
// 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.");
return;
//Platform.exit();
}
if (windows) {
File file = new File("./resources/main/cogwheel-win.png");
// IconPath =this.getClass().getResource("cogwheel-windows.png");
IconPath =file.toURI().toURL();
}
else {
File file = new File("./resources/main/cogwheel-mac.png");
// IconPath =this.getClass().getResource("cogwheel-mac.png");
IconPath =file.toURI().toURL();
}
logger.info(IconPath.getFile().toString());
trayIconImage = ImageIO.read(IconPath);
trayIcon = new TrayIcon(trayIconImage);
startRecording = new MenuItem("Start Recording (Shift+Space)");
stopRecording = new MenuItem("Stop Recording (Shift+Space)");
playRecording = new MenuItem("Play Recording (Shift+P)");
pauseRecording = new MenuItem("Pause Recording (Shift+P)");
startOver = new MenuItem("Start Over (Shift+R)");
//openItem.addActionListener(event -> Platform.runLater(this::showStage));
// and select the exit option, this will shutdown JavaFX and remove the
// tray icon (removing the tray icon will also shut down AWT).
exitItem = new MenuItem("Quit CAD");
exitItem.addActionListener(event -> {
Platform.exit();
tray.remove(trayIcon);
});
// setup the popup menu for the application.
popup.add(startRecording);
popup.add(stopRecording);
popup.addSeparator();
popup.add(playRecording);
popup.add(pauseRecording);
popup.addSeparator();
popup.add(startOver);
popup.addSeparator();
popup.add(exitItem);
trayIcon.setPopupMenu(popup);
// add the application tray icon to the system tray.
tray.add(trayIcon);
// startRecording.addActionListener(event -> Platform.runLater(Creator::startRecording));
} catch (AWTException | IOException e) {
System.out.println("Unable to init system tray");
logger.info(e.getMessage());
}
}
}
I write apps like this a lot, and this is what I discovered as being the easiest and most effective way to use Java/FX to create an app on MacOS that only exists as an icon in the system tray.
I utilize the FXTrayIcon library to accomplish this as that library does the conversions between JavaFX and AWT quite nicely.
First I just add this to my POM file:
<dependency>
<groupId>com.dustinredmond.fxtrayicon</groupId>
<artifactId>FXTrayIcon</artifactId>
<version>3.3.0</version>
</dependency>
Then I use a Launcher class which takes advantage of what AWT can do that JavaFX cannot which is get rid of the Dock icon (not to mention still no native FX support for the system tray).
import java.awt.*;
public class Launcher {
public static void main(String[] args) {
System.setProperty("apple.awt.UIElement", "true");
Toolkit.getDefaultToolkit();
Main.main(args);
}
}
Then here is a simple Main class that is fully functional
import com.dustinredmond.fxtrayicon.FXTrayIcon;
import javafx.application.Application;
import javafx.stage.Stage;
import java.net.URL;
public class Main extends Application {
private URL icon = Main.class.getResource("icon.png");
#Override public void start(Stage primaryStage) throws Exception {
new FXTrayIcon.Builder(primaryStage, icon, 22, 22)
.menuItem("Say Hello", e->helloIcon())
.separator()
.addExitMenuItem("Exit", e-> System.exit(0))
.show()
.build();
}
private void helloIcon() {
System.out.println("Hello Icon");
}
public static void main(String[] args) {
launch(args);
}
}
This is what it looks like, and no Dock icon at all nor does the app show up in the CMD+TAB app switching.
My java application shows its icon on the system tray using code that looks more or less like this:
Toolkit mainToolkit = Toolkit.getDefaultToolkit();
SystemTray mainTray = SystemTray.getSystemTray();
Image trayIconImage = mainToolkit.createImage(getClass().getResource(resourcePath));
TrayIcon mainTrayIcon = new TrayIcon(trayIconImage);
mainTray.add(mainTrayIcon);
Sometimes I change that icon like this:
Image newImage = mainToolkit.createImage(getClass().getResource(otherPath));
mainTrayIcon.setImage(newImage);
From time to time my app needs to show some notification (using a baloon message coming from its tray icon):
mainTrayIcon.displayMessage(someCaption, msg, TrayIcon.MessageType.NONE);
All this code is actually somehow simplified but grasps this functionality pretty well.
So everything's fine on Windows 7. But it turns out that on Windows 10 it is being shown differently. On the notification there's an icon shown on the left. It usually is my app's current tray icon, but sometimes it's just blank:
In the upper red circle (on the notification) is that blank icon which sometimes appears instead of my app's icon (in the lower red circle, on the system's tray). I have no idea why does it occur. All I know is this happens only when the app's tray icon and notification message change before first notification (which always shows its icon correctly) disappears. If the notification is shown, then fades / is closed manually AND THEN app's tray icon and notifications change, next notification (with new message that was just set) will show app's icon correctly.
Just came across this issue and found the correct solution:
mainTrayIcon.setImageAutoSize(true);
Here's a method to send a notification on Windows:
public static void sendNotification(String title, String subtitle, String pathToIcon) {
SystemTray mainTray = SystemTray.getSystemTray();
Image trayIconImage = Toolkit.getDefaultToolkit().getImage(pathToIcon);
TrayIcon mainTrayIcon = new TrayIcon(trayIconImage);
mainTrayIcon.setImageAutoSize(true);
try {
mainTray.add(mainTrayIcon);
mainTrayIcon.displayMessage(title, subtitle, TrayIcon.MessageType.NONE);
}
catch (Exception e) {
e.printStackTrace();
}
}
Calling sendNotification("Title", "Subtitle", "icons/icon-128.png"); shows
//this method to showing notification
public void notifacation(String filenamev, String tooltipv, String etats, String textv, String capationv, String messagetype) {
try {
//Obtain only one instance of the SystemTray object
SystemTray tray = SystemTray.getSystemTray();
// If you want to create an icon in the system tray to preview
Image image = Toolkit.getDefaultToolkit().createImage(filenamev);
//Alternative (if the icon is on the classpath):
//Image image = Toolkit.getDefaultToolkit().createImage(getClass().getResource("icon.png"));
TrayIcon trayIcon = new TrayIcon(image, tooltipv);
//Let the system resize the image if needed
trayIcon.setImageAutoSize(true);
//Set tooltip text for the tray icon
trayIcon.setToolTip(etats);
tray.add(trayIcon);
// Display info notification:
// trayIcon.displayMessage(capationv, textv, TrayIcon.MessageType.ERROR
trayIcon.displayMessage(capationv, textv, MessageType.valueOf(messagetype));
// Error:
// trayIcon.displayMessage("Hello, World", "Java Notification Demo", MessageType.ERROR);
// Warning:
// trayIcon.displayMessage("Hello, World", "Java Notification Demo", MessageType.WARNING);
} catch (Exception ex) {
System.err.print(ex);
}
}
I've found an example in Oracle docs about SplashScreen. the problem is in this example the link of the image used here is passed as argument in the command line.
I'm trying to change the code so the link is written inside and I don't need to use the command line.
methode setImageURL(URL imageURL) should be able to do the work for me, but it's not accepting my argument (parameter).
I read about URL class, seems like it needs protocol! protocol like http and ftp ? if that's the case, how should my url be for files in my computer ? when I try to put a link from my computer (ex: "C:\plash.gif") it says illege excape character
I even tried to use http link for an image but it give me this error within the URL line:
non-static method setImageURL(URL) cannot be referenced from a static context
here's the code:
package misc;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
public class SplashDemo extends Frame implements ActionListener {
static void renderSplashFrame(Graphics2D g, int frame) {
final String[] comps = {"foo", "bar", "baz"};
g.setComposite(AlphaComposite.Clear);
g.fillRect(120,140,200,40);
g.setPaintMode();
g.setColor(Color.BLACK);
g.drawString("Loading "+comps[(frame/5)%3]+"...", 120, 150);
}
public SplashDemo() {
super("SplashScreen demo");
setSize(300, 200);
setLayout(new BorderLayout());
Menu m1 = new Menu("File");
MenuItem mi1 = new MenuItem("Exit");
m1.add(mi1);
mi1.addActionListener(this);
this.addWindowListener(closeWindow);
MenuBar mb = new MenuBar();
setMenuBar(mb);
mb.add(m1);
URL link= new URL("http://docs.oracle.com/javase/tutorial/uiswing/examples/misc/SplashDemoProject/src/misc/images/splash.gif");
SplashScreen.setImageURL(link);
final SplashScreen splash = SplashScreen.getSplashScreen();
if (splash == null) {
System.out.println("SplashScreen.getSplashScreen() returned null");
return;
}
Graphics2D g = splash.createGraphics();
if (g == null) {
System.out.println("g is null");
return;
}
for(int i=0; i<100; i++) {
renderSplashFrame(g, i);
splash.update();
try {
Thread.sleep(90);
}
catch(InterruptedException e) {
}
}
splash.close();
setVisible(true);
toFront();
}
public void actionPerformed(ActionEvent ae) {
System.exit(0);
}
private static WindowListener closeWindow = new WindowAdapter(){
public void windowClosing(WindowEvent e){
e.getWindow().dispose();
}
};
public static void main (String args[]) {
SplashDemo test = new SplashDemo();
}
}
this is the output:
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - unreported exception java.net.MalformedURLException; must be caught or declared to be thrown
at misc.SplashDemo.main(SplashDemo.java:103)
Java Result: 1
BUILD SUCCESSFUL (total time: 4 seconds)
and nothing happens.
P.S: I'm a very beginner with Java, I'm using NetBeans IDE 7.2.1
The splash screen can be displayed at application startup, before the Java Virtual Machine (JVM) starts.
The splash screen window is closed automatically as soon as the first window is displayed by Swing/AWT (may be also closed manually using the Java API, see below).
If your application is packaged in a jar file, you can use the
SplashScreen-Image option in a manifest file to show a splash screen.
Place the image in the jar archive and specify the path in the option.
The path should not have a leading slash.
For example, in the manifest.mf file:
Manifest-Version: 1.0
Main-Class: Test
SplashScreen-Image: filename.gif
The SplashScreen class provides the API for controlling the splash screen.
This class may be used to
close the splash screen
change the splash screen image
get the splash screen native window position/size
paint in the splash screen.
It cannot be used to create the splash screen.
This class cannot be instantiated.
Only a single instance of this class can exist, and it may be obtained by using the getSplashScreen() static method.
In case the splash screen has not been created at application startup via the command line or manifest file option,
the getSplashScreen method returns null.
so what is wrong with your code?
NOT
SplashScreen.setImageURL(link);
OK
splash.setImageURL(link);
wrong sequence : Setting ImageUrl before you have a splash Object
URL link= new URL("http://docs.oracle.com/javase/tutorial/uiswing/examples/misc/SplashDemoProject/src/misc/images/splash.gif");
SplashScreen.setImageURL(link);
final SplashScreen splash = SplashScreen.getSplashScreen();
correct : Get splash and then set ImageUrl
short
final SplashScreen splash = SplashScreen.getSplashScreen();
splash.setImageURL(link);
long with catch MalformedURLException to get rid of the error
MalformedURLException : must be caught
final SplashScreen splash = SplashScreen.getSplashScreen();
if (splash == null) {
System.out.println("SplashScreen.getSplashScreen() returned null");
return;
}
URL link;
try {
link = new URL("http://docs.oracle.com/javase/tutorial/uiswing/examples/misc/SplashDemoProject/src/misc/images/splash.gif");
} catch (MalformedURLException ex) {
System.out.println("MalformedURLException link:77");
return;
}
try {
splash.setImageURL(link);
} catch (NullPointerException | IOException | IllegalStateException ex) {
System.out.println("NullPointer or IO or IllegalState setImageUrl:85");
return;
}
To recognize the difference between the local image file and the image file on the internet . I have made a local blue splash.gif file.
The proceeding is as follows.
Local image is loaded. (SplashScreen-Image option in the manifest file)
Internet image is loaded. (//docs.oracle.com...images/splash.gif)
Application appears.
To get it to work in Netbeans
and not always get the error SplashScreen.getSplashScreen() returned null
final SplashScreen splash = SplashScreen.getSplashScreen();
if (splash == null) {
System.out.println("SplashScreen.getSplashScreen() returned null");
you must do the following.
in properties point to your local .gif file : -splash:src/misc/images/splash.gif
I am using the following code to set a tray icon in Windows and Linux. It works wonderful in Windows and works okay in Linux. In Linux (Ubuntu) I have my panel set to be (somewhat) transparent and when I add a GIF (with a transparent background) the background of the icon shows up all grey and ugly (see image, green diamond "!")....Any ideas on how to make the GIF image I am adding "keep" its transparent background?
alt text http://unarm.org/stackoverflow/panel_task.jpg
and the image I am using, if you'd like to test:
alt text http://unarm.org/stackoverflow/green_info.gif
import java.awt.*;
import java.awt.event.*;
public class TrayFun {
static class ShowMessageListener implements ActionListener {
TrayIcon trayIcon;
String title;
String message;
TrayIcon.MessageType messageType;
ShowMessageListener(
TrayIcon trayIcon,
String title,
String message,
TrayIcon.MessageType messageType) {
this.trayIcon = trayIcon;
this.title = title;
this.message = message;
this.messageType = messageType;
}
public void actionPerformed(ActionEvent e) {
trayIcon.displayMessage(title, message, messageType);
}
}
public static void main(String args[]) {
Runnable runner = new Runnable() {
public void run() {
if (SystemTray.isSupported()) {
final SystemTray tray = SystemTray.getSystemTray();
Image image = Toolkit.getDefaultToolkit().getImage("green_info.png");
PopupMenu popup = new PopupMenu();
final TrayIcon trayIcon = new TrayIcon(image, "The Tip Text", popup);
trayIcon.setImageAutoSize(true);
MenuItem item = new MenuItem("Close");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tray.remove(trayIcon);
}
});
popup.add(item);
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.err.println("Can't add to tray");
}
} else {
System.err.println("Tray unavailable");
}
}
};
EventQueue.invokeLater(runner);
}
}
The problem lies in the sun.awt.X11.XTrayIconPeer.IconCanvas.paint() method!
Before painting, the icon background is amateurishly cleared by simply drawing a rectangle of IconCanvas’ background color, to allow image animations.
public void paint(Graphics g) {
if (g != null && curW > 0 && curH > 0) {
BufferedImage bufImage = new BufferedImage(curW, curH, BufferedImage.TYPE_INT_ARGB);
Graphics2D gr = bufImage.createGraphics();
if (gr != null) {
try {
gr.setColor(getBackground());
gr.fillRect(0, 0, curW, curH);
gr.drawImage(image, 0, 0, curW, curH, observer);
gr.dispose();
g.drawImage(bufImage, 0, 0, curW, curH, null);
} finally {
gr.dispose();
}
}
}
}
see: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6453521
For those looking for a "real" solution, I developed a small library that is capable of displaying the tray icon honoring the transparency and also accepts SVG icons (for all platforms):
http://skype2gmail.blogspot.com/2011/05/java-tray-icon-transparency.html
It is an open source library and the source code can be found here:
https://github.com/taksan/native-tray-adapter
The library work arounds the problem by providing a JNI alternative (with GTK) when running under linux.
Chances are this problem cannot be resolved. It depends on wether Java is doing a good job in creating the tray subwindow in Linux or not. If Jave does it wrong, transparency is already lost when the image is drawn.
What is the real background value of the icon you are using? Is it the gray tone shown above? Set it to purple to see if the transparency of the image is used (Java defaults to gray background) or not.
Make sure you tried both transparency options of PNG: transparent color index as well as alpha channel. Alpha channel is very common in Linux, not so in the Windows world.
The resolution of your icon is too small. Do it in 64x64 or better 128x128. AFAIK there is no standard resolution for tray icons, and even if so, it is certainly not 16x16.
Another format you could try is SVG. Only try that after making sure that the transparency of the image is the problem (see 1).
See here for background information on this issue:
http://www.rasterman.com/index.php?page=News (scroll down to 2 February 2006)
JDIC has a tray icon, they might support transparency in linux...
https://jdic.dev.java.net/
Have you tried converting it to a .PNG (with transparency) instead? I've found they tend to be better supported by Java (In my experience)
its not that . . . this is happing because it is using the default GNOME theme for rendering the transparency - it has nothing to do with the image it self - this is an adobe air / gnome conflict - if you switch to a gnome theme were the default background is grey then it would be grey instead of white. It uses the system default image so even if it was set but the theme for the panel to have a BG image to make it look glossy like vista for example than it would do that. Adobe Air / Java doesn't know that you over road the theme default with transparency and therefor it is using the system default