java's SystemTray not working on Gnome 3.14 - java

I'm trying to put a Java SystemTray icon on gnome's notification panel (I'm using OpenSuse 13.2, that uses gnome 3.14).
Its not working, although SystemTray.isSupported() is returning "true". I'm not seeing any icon on the screen. I was expecting it to appear next to OpenSuse's notification area.
This is the main's code:
public static void main(String[] args) {
//checking for support
if (!SystemTray.isSupported()) {
System.out.println("System tray is not supported !!! ");
return;
}
SystemTray systemTray = SystemTray.getSystemTray();
Image image = Toolkit.getDefaultToolkit().getImage("icon.ico");
//popupmenu
PopupMenu trayPopupMenu = new PopupMenu();
//1t menuitem for popupmenu
MenuItem action = new MenuItem("Action");
action.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "Action Clicked");
}
});
trayPopupMenu.add(action);
//2nd menuitem of popupmenu
MenuItem close = new MenuItem("Close");
close.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
trayPopupMenu.add(close);
//setting tray icon
TrayIcon trayIcon = new TrayIcon(image, "SystemTray Demo", trayPopupMenu);
//adjust to default size as per system recommendation
trayIcon.setImageAutoSize(true);
try {
systemTray.add(trayIcon);
} catch (AWTException awtException) {
awtException.printStackTrace();
}
System.out.println("end of main");
}//end of main

Related

Java restore JFrame from tray

I have an applicaton that implements a listener for smartcards reader.
When I run the application I send it to tray.
When the aplication detects a card I want it to restore the jFrame back to normal so the user can select the options available on the screen.
Problem is when I try to restore the window it creates a new one.
How is possible to restore the jFrame back to normal.
This code is what I have inside the jFrame constructor:
It creates the tray Icon and the options Close and Open. But I want it to open automatically. Is it possible to programatically click the Open option?
initComponents();
setResizable(false);
setLocationRelativeTo(null);
setTitle("App Title");
UFRInstance = (uFrFunctions) Native.loadLibrary(GetLibFullPath(false), uFrFunctions.class);
this.wsc = new WebSocketConnection();
System.out.println("creating instance");
try {
System.out.println("setting look and feel");
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
System.out.println("Unable to set LookAndFeel");
}
if (SystemTray.isSupported()) {
System.out.println("system tray supported");
tray = SystemTray.getSystemTray();
Image image = Toolkit.getDefaultToolkit().getImage("bulb.png");
ActionListener exitListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Exiting....");
System.exit(0);
}
};
PopupMenu popup = new PopupMenu();
MenuItem defaultItem = new MenuItem("Close");
defaultItem.addActionListener(exitListener);
popup.add(defaultItem);
defaultItem = new MenuItem("Open");
defaultItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setVisible(true);
setExtendedState(JFrame.NORMAL);
}
});
popup.add(defaultItem);
trayIcon = new TrayIcon(createIcon("bulb.png", "Icon"), "SystemTray Demo", popup);
trayIcon.setImageAutoSize(true);
} else {
System.out.println("system tray not supported");
}
addWindowStateListener(new WindowStateListener() {
public void windowStateChanged(WindowEvent e) {
if (e.getNewState() == ICONIFIED) {
try {
tray.add(trayIcon);
setVisible(false);
System.out.println("added to SystemTray");
} catch (AWTException ex) {
System.out.println("unable to add to tray");
}
}
if (e.getNewState() == 7) {
try {
tray.add(trayIcon);
setVisible(false);
System.out.println("added to SystemTray");
} catch (AWTException ex) {
System.out.println("unable to add to system tray");
}
}
if (e.getNewState() == MAXIMIZED_BOTH) {
tray.remove(trayIcon);
setVisible(true);
System.out.println("Tray icon removed");
}
if (e.getNewState() == NORMAL) {
tray.remove(trayIcon);
setVisible(true);
System.out.println("Tray icon removed1");
}
}
});
setIconImage(Toolkit.getDefaultToolkit().getImage("bulb.png"));
setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("bulb.png")));
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
You code contains the "Open" option, adding an ActionListener:
defaultItem = new MenuItem("Open");
defaultItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setVisible(true);
setExtendedState(JFrame.NORMAL);
}
So all you need to do is call setVisible(true); and maybe the second line as well.
You need to do visible. Like Below example :
int state = getExtendedState();
state = state & ~Frame.ICONIFIED;
setExtendedState(state);
setVisible(true);
The first line retrieves the current state, which is a bitmask. It then sets the ICONIFIED (minimized) part to false, then sets the same state again. This way, if the program was maximized before it will be maximimized again, etc. Of course a setVisible(true) must follow to show the window again.

Hide Java application to System Tray

I want to hide my Java application from the taskbar and for it to be visible only at the system tray. Here is a picture in case this is unclear.
I tried to implement it like this and the icon did appear in the system tray but it is still showing the application on the taskbar.
Here is part of the Frame class
public class Widget extends JFrame {
private static final long serialVersionUID = -197136854089859547L;
private JPanel mainPanel;
private WidgetProperties properties;
private Makedir mkdir;
private ArrayList<Item> items;
private Image icon;
private TrayIcon trayIcon;
private SystemTray tray;
public Widget() {
super("");
this.setTray();
this.setUndecorated(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void setTray() {
tray = SystemTray.getSystemTray();
PopupMenu menu = new PopupMenu();
MenuItem show = new MenuItem("Show");
MenuItem exit = new MenuItem("Exit");
show.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
setState(Frame.NORMAL);
}
});
exit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
close();
}
});
menu.add(show);
menu.addSeparator();
menu.add(exit);
trayIcon = new TrayIcon(icon, "EasyStart", menu);
trayIcon.setImageAutoSize(true);
try
{
tray.add(trayIcon);
} catch (AWTException e) {
e.printStackTrace();
}
}
public void setup() {
this.resize();
this.setVisible(true);
}
public void resize() {
this.setResizable(true);
this.setShape(properties.getShape());
this.setSize(properties.getSize());
this.setResizable(false);
}
public void close() {
System.exit(0);
}
}
I just need to find how to hide the application from the taskbar.
do this setVisible(false) then there will be nothing in the taskbar

Cannot hide SystemTray JPopupMenu when it loses focus

This question is similar to this one. What I have is a JPopupMenu that pops up from an icon on the system tray. At this point, the system tray is the only manifestation of the program. That is, there are no other windows open, the icon in the system tray is the only way I can access the program. I used a JPopupMenu over the AWT PopupMenu because I wanted to get the system Look and Feel applied to the popup menu - when I used just a plain PopupMenu, I could not get the system's Look and Feel, I just kept getting Swing's Metal Look and Feel. I used this work-around to get this behavior (described here):
systemTrayPopupMenu = buildSystemTrayJPopupMenu();
trayIcon = new TrayIcon(iconImage, "Application Name", null /* Popup Menu */);
trayIcon.addMouseListener (new MouseAdapter () {
#Override
public void mouseReleased (MouseEvent me) {
if (me.isPopupTrigger()) {
systemTrayPopupMenu.setLocation(me.getX(), me.getY());
systemTrayPopupMenu.setInvoker(systemTrayPopupMenu);
systemTrayPopupMenu.setVisible(true);
}
}
};
When I right click on the tray icon, it shows the menu, and naturally, when I make a selection, the menu disappears. However, when I bring up the menu, then click out of it, it does not disappear. To make it disappear currently, I have to either make a selection, or select one of the menu items that are disabled.
I tried adding a FocusListener to it, however, there is no indication that the focusLost or focusGained methods ever get called. Additionally, I cannot make it disappear when another Window gains focus because there are no other windows present. Since this pop-up menu comes from a TrayIcon and not a typical button, I cannot use the solution mentioned here to get around the FocusListener not calling focusLost.
Ultimately, what I am wondering is either:
1) Is there a way to get the system's look and feel for a normal AWT PopupMenu?, or
2) Is there a way to make the JPopupMenu disappear when it loses focus?
EDIT: Per request, here is my SSCCE:
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class SwingSystemTray {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run () {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new SwingSystemTray ();
} catch (Exception e) {
System.out.println("Not using the System UI defeats the purpose...");
e.printStackTrace();
}
}
});
}
protected SystemTray systemTray;
protected TrayIcon trayIcon;
protected JPopupMenu systemTrayPopupMenu;
protected Image iconImage;
public SwingSystemTray () throws IOException {
iconImage = getIcon ();
if (SystemTray.isSupported()) {
systemTray = SystemTray.getSystemTray();
systemTrayPopupMenu = buildSystemTrayJPopupMenu();
trayIcon = new TrayIcon(iconImage, "Application Name", null /* Popup Menu */);
trayIcon.addMouseListener (new MouseAdapter () {
#Override
public void mouseReleased (MouseEvent me) {
if (me.isPopupTrigger()) {
systemTrayPopupMenu.setLocation(me.getX(), me.getY());
systemTrayPopupMenu.setInvoker(systemTrayPopupMenu);
systemTrayPopupMenu.setVisible(true);
}
}
});
try {
systemTray.add(trayIcon);
} catch (AWTException e) {
System.out.println("Could not place item at tray. Exiting.");
}
}
}
protected JPopupMenu buildSystemTrayJPopupMenu () {
final JPopupMenu menu = new JPopupMenu ();
final JMenuItem showMenuItem = new JMenuItem("Show");
final JMenuItem hideMenuItem = new JMenuItem("Hide");
final JMenuItem exitMenuItem = new JMenuItem("Exit");
hideMenuItem.setEnabled(false);
ActionListener listener = new ActionListener () {
#Override
public void actionPerformed (ActionEvent ae) {
Object source = ae.getSource();
if (source == showMenuItem) {
System.out.println("Shown");
showMenuItem.setEnabled(false);
hideMenuItem.setEnabled(true);
}
else if (source == hideMenuItem) {
System.out.println("Hidden");
hideMenuItem.setEnabled(false);
showMenuItem.setEnabled(true);
}
else if (source == exitMenuItem) {
System.exit(0);
}
}
};
for (JMenuItem item : new JMenuItem [] {showMenuItem, hideMenuItem, exitMenuItem}) {
if (item == exitMenuItem) menu.addSeparator();
menu.add(item);
item.addActionListener(listener);
}
return menu;
}
protected Image getIcon () throws IOException {
// Build the 16x16 image programmatically, start with BMP Header
byte [] iconData = new byte[822];
System.arraycopy(new byte [] {0x42,0x4d,0x36,0x03, 0,0,0,0, 0,0,0x36,0,
0,0,0x28,0, 0,0,16,0, 0,0,16,0, 0,0,16,0, 24,0,0,0, 0,0,0,3},
0, iconData, 0, 36);
for (int i = 36; i < 822; iconData[i++] = 0);
for (int i = 56; i < 822; i += 3) iconData[i] = -1;
return ImageIO.read(new java.io.ByteArrayInputStream(iconData));
}
}
I found a hack that I feel will work just nicely. I have yet to test it in Windows XP, but it works in Windows 7. This involves adding a "hidden dialog" that displays behind the popup menu, as if the popup menu originated from the hidden dialog in the first place. The only real trick is getting the hidden dialog to stay behind the popup menu. At least in Windows 7, it displays behind the system tray, so you never really see it in the first place. A WindowFocusListener can be added to this hidden dialog, and so when you click out of the popup menu, you are also clicking out of the hidden dialog. I have added this capability to the SSCCE that I posted previously to illustrate how adding this works:
package org.test;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class SwingSystemTray {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run () {
try {
/* We are going for the Windows Look and Feel here */
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new SwingSystemTray ();
} catch (Exception e) {
System.out.println("Not using the System UI defeats the purpose...");
e.printStackTrace();
}
}
});
}
protected SystemTray systemTray;
protected TrayIcon trayIcon;
protected JPopupMenu systemTrayPopupMenu;
protected Image iconImage;
/* Added a "hidden dialog" */
protected JDialog hiddenDialog;
public SwingSystemTray () throws IOException {
iconImage = getIcon ();
if (SystemTray.isSupported()) {
systemTray = SystemTray.getSystemTray();
systemTrayPopupMenu = buildSystemTrayJPopupMenu();
trayIcon = new TrayIcon(iconImage, "Application Name", null /* Popup Menu */);
trayIcon.addMouseListener (new MouseAdapter () {
#Override
public void mouseReleased (MouseEvent me) {
if (me.isPopupTrigger()) {
systemTrayPopupMenu.setLocation(me.getX(), me.getY());
/* Place the hidden dialog at the same location */
hiddenDialog.setLocation(me.getX(), me.getY());
/* Now the popup menu's invoker is the hidden dialog */
systemTrayPopupMenu.setInvoker(hiddenDialog);
hiddenDialog.setVisible(true);
systemTrayPopupMenu.setVisible(true);
}
}
});
trayIcon.addActionListener(new ActionListener() {
#Override
public void actionPerformed (ActionEvent ae) {
System.out.println("actionPerformed");
}
});
try {
systemTray.add(trayIcon);
} catch (AWTException e) {
System.out.println("Could not place item at tray. Exiting.");
}
}
/* Initialize the hidden dialog as a headless, titleless dialog window */
hiddenDialog = new JDialog ();
hiddenDialog.setSize(10, 10);
/* Add the window focus listener to the hidden dialog */
hiddenDialog.addWindowFocusListener(new WindowFocusListener () {
#Override
public void windowLostFocus (WindowEvent we ) {
hiddenDialog.setVisible(false);
}
#Override
public void windowGainedFocus (WindowEvent we) {}
});
}
protected JPopupMenu buildSystemTrayJPopupMenu () {
final JPopupMenu menu = new JPopupMenu ();
final JMenuItem showMenuItem = new JMenuItem("Show");
final JMenuItem hideMenuItem = new JMenuItem("Hide");
final JMenuItem exitMenuItem = new JMenuItem("Exit");
hideMenuItem.setEnabled(false);
ActionListener listener = new ActionListener () {
#Override
public void actionPerformed (ActionEvent ae) {
/* We want to make sure the hidden dialog goes away after selection */
hiddenDialog.setVisible(false);
Object source = ae.getSource();
if (source == showMenuItem) {
System.out.println("Shown");
showMenuItem.setEnabled(false);
hideMenuItem.setEnabled(true);
}
else if (source == hideMenuItem) {
System.out.println("Hidden");
hideMenuItem.setEnabled(false);
showMenuItem.setEnabled(true);
}
else if (source == exitMenuItem) {
System.exit(0);
}
}
};
for (JMenuItem item : new JMenuItem [] {showMenuItem, hideMenuItem, exitMenuItem}) {
if (item == exitMenuItem) menu.addSeparator();
menu.add(item);
item.addActionListener(listener);
}
return menu;
}
protected Image getIcon () throws IOException {
// Build the 16x16 image programmatically, start with BMP Header
byte [] iconData = new byte[822];
System.arraycopy(new byte [] {0x42,0x4d,0x36,0x03, 0,0,0,0, 0,0,0x36,0,
0,0,0x28,0, 0,0,16,0, 0,0,16,0, 0,0,16,0, 24,0,0,0, 0,0,0,3},
0, iconData, 0, 36);
for (int i = 36; i < 822; iconData[i++] = 0);
for (int i = 56; i < 822; i += 3) iconData[i] = -1;
return ImageIO.read(new java.io.ByteArrayInputStream(iconData));
}
}
This solution gives me requirement #2 that I was looking for, which is to make the JPopupMenu disappear when it loses focus on a system tray using the Windows system look and feel.
Note: I have not gotten the JPopupMenu feature to work on the system tray in CentOS/RedHat Linux. For those, I will have to just use a normal AWT PopupMenu.
A JPopupMenu can't be displayed by itself. That is it needs to be added to a window. Try to use a WindowListener and then hide the popup on a windowDeactivated() event. After the popup is visible you should be able to get the window by using:
Window window = SwingUtilities.windowForComonent(systemTrayPopupMenu);
I just used a MouseListener on the JPopup menu which invokes a timer Thread upon mouse exit; if the mouse re-enters, I reset the "mouseStillOnMenu" flag. Set the "Thread.sleep() value to however long you want the user to be able leave the menu - if you click on a a menu item normally, the default menu close behavior is invoked and closes the menu.
#Override
public void mouseEntered(MouseEvent arg0) {
mouseStillOnMenu = true;
}
#Override
public void mouseExited(MouseEvent arg0) {
mouseStillOnMenu = false;
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000); //waits one second before checking if mouse is still on the menu
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (!isMouseStillOnMenu()) {
jpopup.setVisible(false);
}
}
}).start();
}

Java popup menu listen for item clicks?

Im creating a very simple tray menu with the following code:
final Frame frame = new Frame("");
frame.setUndecorated(true);
// Check the SystemTray is supported
if (!SystemTray.isSupported()) {
System.out.println("SystemTray is not supported");
return;
}
final TrayIcon trayIcon = new TrayIcon(Toolkit.getDefaultToolkit().getImage(
new URL("http://url.com/trayIcon.png")), "Library Drop");
final SystemTray tray = SystemTray.getSystemTray();
// Create a pop-up menu components
final PopupMenu popup = createPopupMenu();
trayIcon.setPopupMenu(popup);
trayIcon.addMouseListener(new MouseAdapter() {
//#Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
frame.add(popup);
popup.show(frame, e.getXOnScreen(), e.getYOnScreen());
}
}
});
try {
frame.setResizable(false);
frame.setVisible(true);
tray.add(trayIcon);
} catch (AWTException e) {
System.out.println("TrayIcon could not be added.");
}
} catch (MalformedURLException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
protected static PopupMenu createPopupMenu() {
final PopupMenu popup = new PopupMenu();
MenuItem aboutItem = new MenuItem("Accept");
MenuItem aboutItem1 = new MenuItem("Dont accept");
MenuItem aboutItem2 = new MenuItem("Quit");
// Add components to pop-up menu
popup.add(aboutItem);
popup.add(aboutItem1);
popup.addSeparator();
popup.add(aboutItem2);
return popup;
}
How can i listen and check when a user selects "Accept", "Dont accept", etc?
Also for some reason the height is maximum on the trayIcon, how can i tell the tray icon to be exactly X by Y pixles?
Edit: height/width issue is only in Mac, works fine on Windows
Simply use addActionListener on your MenuItems.
MenuItem aboutItem = new MenuItem("Accept");
aboutItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
System.out.println("Accept clicked!");
}
});
Also, if you happen to be using Java 8 or later, it becomes even simpler:
MenuItem aboutItem = new MenuItem("Accept");
aboutItem.addActionListener(evt -> System.out.println("Accept clicked!"));

Java in background of windows for copying text from the browser directly to text file

Is it possible to listen to events from browser with Java?
The main task is to add command "copy to file" to pop-up menu of right click of the mouse. This command must add selected text in browser, in Notepad, in winword (any selectable text) to specific text file.
I've just tried code which adds icon to tray but I do not know whether it can it be developed for solving my task.
import java.awt.*;
import java.awt.event.*;
public class SystemTrayTest
{
public SystemTrayTest()
{
final TrayIcon trayIcon;
if (SystemTray.isSupported()) {
SystemTray tray = SystemTray.getSystemTray();
Image image = Toolkit.getDefaultToolkit().getImage("tray.gif");
MouseListener mouseListener = new MouseListener() {
public void mouseClicked(MouseEvent e) {
System.out.println("Tray Icon - Mouse clicked!");
}
public void mouseEntered(MouseEvent e) {
System.out.println("Tray Icon - Mouse entered!");
}
public void mouseExited(MouseEvent e) {
System.out.println("Tray Icon - Mouse exited!");
}
public void mousePressed(MouseEvent e) {
System.out.println("Tray Icon - Mouse pressed!");
}
public void mouseReleased(MouseEvent e) {
System.out.println("Tray Icon - Mouse released!");
}
};
ActionListener exitListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Exiting...");
System.exit(0);
}
};
PopupMenu popup = new PopupMenu();
MenuItem defaultItem = new MenuItem("Exit");
defaultItem.addActionListener(exitListener);
popup.add(defaultItem);
trayIcon = new TrayIcon(image, "Tray Demo", popup);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
trayIcon.displayMessage("Action Event",
"An Action Event Has Been Peformed!",
TrayIcon.MessageType.INFO);
}
};
trayIcon.setImageAutoSize(true);
trayIcon.addActionListener(actionListener);
trayIcon.addMouseListener(mouseListener);
// Depending on which Mustang build you have, you may need to uncomment
// out the following code to check for an AWTException when you add
// an image to the system tray.
// try {
tray.add(trayIcon);
// } catch (AWTException e) {
// System.err.println("TrayIcon could not be added.");
// }
} else {
System.err.println("System tray is currently not supported.");
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
SystemTrayTest main = new SystemTrayTest();
}
}
You are talking about accessing clipboard events. this may helps you. How do we get notified about system clipboard events?

Categories