I need some guidance in how to get the application to show up from the System Tray when I click on it.
I have managed to minimize the app on closure but I can't make it to show up.
If I'm builduing a new shell with same Contents would help?(I am building a SWT application)
This is how I am initializing my Shell: (I have modified it so I don't use AWT with SWT)
protected Shell shlSmartHouseSystem;
public void open() {
Display display = Display.getDefault();
createContents();
shlSmartHouseSystem.open();
shlSmartHouseSystem.layout();
while (!shlSmartHouseSystem.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
And this is my function where I am minimizing in Tray:
public void minimizeToTrayOnClose() {
final Display display = shlSmartHouseSystem.getDisplay();
Image image = new Image(display,"D:\\VIA_University_(Embedded_Systems)\\AJP_Workspace\\HouseSystem_Server\\icon-smart-house.png");
Tray tray = display.getSystemTray();
if (tray != null) {
TrayItem trayItm = new TrayItem(tray,SWT.NONE);
trayItm.setImage(image);
final Menu menu = new Menu(shlSmartHouseSystem, SWT.POP_UP);
MenuItem menuItem = new MenuItem(menu, SWT.PUSH);
menuItem.setText("Show");
menuItem.addListener (SWT.Selection, new Listener () {
public void handleEvent (Event e) {
System.out.println("Opened");
}
});
menuItem = new MenuItem(menu, SWT.PUSH);
menuItem.setText("Exit");
menuItem.addListener (SWT.Selection, new Listener () {
public void handleEvent (Event e) {
System.exit(0);
}
});
trayItm.addListener (SWT.MenuDetect, new Listener () {
public void handleEvent (Event event) {
menu.setVisible (true);
}
});
}
}
Related
I'm adding a PopUp menu to one of my widgets, a Table. It is not working! I only achieved to make work accelerator shortcuts if they are on top menu bar items, and not in popup context menu items. Why?
This is my code, but the table is inside a Composite which is inside another composite:
membersTable.setMenu(createMembersPopUpMenu(this));
private Menu createMembersPopUpMenu(Composite parent) {
Menu popUpMenu = new Menu(parent);
//Copy
copyMemberItem = new MenuItem(popUpMenu, SWT.PUSH);
copyMemberItem.setText("Copiar Miembro");
copyMemberItem.setAccelerator(SWT.MOD1 + 'C');
copyMemberItem.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
copyMember();
}
});
//Paste
pasteMemberItem = new MenuItem(popUpMenu, SWT.PUSH);
pasteMemberItem.setText("Pegar Miembro");
pasteMemberItem.setAccelerator(SWT.MOD1 + 'V');
pasteMemberItem.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
pasteMember();
}
});
return popUpMenu;
}
I have this JFace dialog:
setShellStyle(SWT.APPLICATION_MODAL | SWT.CLOSE);
setBlockOnOpen(false);
Is there a way to make it close by clicking somewhere outside the dialog?
Maybe something like listening for a click event on the whole screen and detecting if it's outside the dialog, and then closing.
You can attach an SWT.Deactivate listener to the underlying Shell of the dialog.
To attach the listener, you could override Window::configureShell like this:
#Override
protected void configureShell(Shell shell) {
super.configureShell(shell);
shell.addListener(SWT.Deactivate, event -> shell.close());
}
And here a standalone SWT example to illustrate the bare mechanism:
Display display = new Display();
Shell parentShell = new Shell(display);
parentShell.setSize(500, 500);
parentShell.open();
Shell shell = new Shell(parentShell);
shell.addListener(SWT.Deactivate, event -> shell.close());
shell.setSize(300, 300);
shell.setText("Closes on Deactivate");
shell.open();
while (!parentShell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
With the Dialog being modal I believe that causes some challenges using the Shell of the base application to listen for MouseEvents because the Dialog intercepts them.
If you're not opposed to using an additional library you could consider using JNativeHook to listen for global mouse click events. This would allow you to listen for a click anywhere on the computer and close the dialog if the click occurred outside the dialog bounds, if that's what you're looking for.
For example:
GlobalScreen.addNativeMouseListener(new NativeMouseInputAdapter() {
public void nativeMouseClicked(final NativeMouseEvent nativeMouseEvent) {
display.syncExec(new Runnable() {
public void run() {
if (dialog.getShell() == null || dialog.getShell().isDisposed()) {
return;
}
// Close the dialog if there is a mouse click outside the bounds of the dialog
if (!dialog.getShell().getBounds().contains(awtToSwtPoint(nativeMouseEvent.getPoint()))) {
dialog.close();
}
}
});
}
});
Other than that, I'm not aware of a way to listen to mouse clicks that are outside of the base application / anywhere on the screen.
Full example:
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseInputAdapter;
public class DialogCloseTest {
private final Display display;
private final Shell shell;
public DialogCloseTest() {
display = new Display();
shell = new Shell(display);
shell.setSize(450, 450);
final Dialog dialog = new MyDialog(shell);
dialog.open();
registerNativeHook();
GlobalScreen.addNativeMouseListener(new NativeMouseInputAdapter() {
public void nativeMouseClicked(final NativeMouseEvent nativeMouseEvent) {
display.syncExec(new Runnable() {
public void run() {
if (dialog.getShell() == null || dialog.getShell().isDisposed()) {
return;
}
// Close the dialog if there is a mouse click outside the bounds of the dialog
if (!dialog.getShell().getBounds().contains(awtToSwtPoint(nativeMouseEvent.getPoint()))) {
dialog.close();
}
}
});
}
});
}
private org.eclipse.swt.graphics.Point awtToSwtPoint(final java.awt.Point point) {
return new org.eclipse.swt.graphics.Point(point.x, point.y);
}
private static void registerNativeHook() {
try {
GlobalScreen.registerNativeHook();
} catch (NativeHookException ex) {
System.err.println("There was a problem registering the native hook.");
System.err.println(ex.getMessage());
System.exit(1);
}
}
private static void unregisterNativeHook() {
try {
GlobalScreen.unregisterNativeHook();
} catch (NativeHookException e) {
System.err.println("There was a problem unregistering the native hook.");
System.err.println(e.getMessage());
}
}
private static class MyDialog extends Dialog {
MyDialog(final Shell parent) {
super(parent);
}
#Override
protected void configureShell(final Shell shell) {
super.configureShell(shell);
setShellStyle(SWT.APPLICATION_MODAL | SWT.CLOSE);
setBlockOnOpen(false);
}
}
public void run() {
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
unregisterNativeHook();
}
public static void main(String... args) {
new DialogCloseTest().run();
}
}
Note: This will close the Dialog even if it is not visible (eg. if you alt-tab away), so you could add some logic to check whether the dialog is visible as well, if you would like)
I'm trying to hide a SWT shell when the Display is minimized. I'm missing something and would be most thankful for any help.
Additional Info: This shell is actually a popup that gets drawn when the user clicks on a composite. In the end, my goal is to hide this popup-shell when the composite is not visible (user minimized the window or switched between windows, say with Alt+Tab for example).
Here's my code:
static Shell middleClickNodeInfoShell ;
static Label nodeIdLabel ;
void init(){
...
/** Focused node on middle click*/
middleClickNodeInfoShell = new Shell(Display.getDefault(), SWT.BORDER | SWT.MODELESS);
middleClickNodeInfoShell.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false));
middleClickNodeInfoShell.setLayout(createNoMarginLayout(1, false));
nodeIdLabel = new Label(middleClickNodeInfoShell, SWT.NONE);
Display.getDefault().addListener(SWT.Iconify,new Listener() {
#Override
public void handleEvent(Event arg0) {
// TODO Auto-generated method stub
middleClickNodeInfoShell.setVisible(false);
}
});
}
#Override
public boolean onMouseClicked(Button button, ScreenPosition screenPos,
final GeoPosition arg2) {
...
nodeIdLabel.setText("Node Id: "+node.getId());
middleClickNodeInfoShell.setLocation(pos.getX()+displayX,pos.getY()+displayY+30);
middleClickNodeInfoShell.setVisible(true);
middleClickNodeInfoShell.pack();
}
Here is sample code that will help you do figure out what you are looking for
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setSize(300, 200);
shell.setText("Shell Example");
shell.setLayout(new RowLayout());
final Button button = new Button(shell, SWT.PUSH);
button.setText("Click Me");
final Shell tip = new Shell(shell,SWT.MODELESS);
tip.setLayout(new FillLayout());
Label lbl = new Label(tip, SWT.NONE);
lbl.setText("***tooltip***");
tip.pack();
shell.addControlListener(new ControlListener() {
#Override
public void controlResized(ControlEvent e) {
changeTipLocation(display, button, tip);
}
#Override
public void controlMoved(ControlEvent e) {
changeTipLocation(display, button, tip);
}
});
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
changeTipLocation(display, button, tip);
tip.open();
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private static void changeTipLocation(final Display display, final Button button, final Shell tip) {
Rectangle bounds = button.getBounds();
Point loc = button.getLocation();
tip.setLocation(display.map(button, null, new Point(loc.x+bounds.width, loc.y+bounds.height)));
}
Consider the following Java (SWT) code:
private static ComboViewer createViewer(final Shell shell) {
final ComboViewer v = new ComboViewer(shell, SWT.DROP_DOWN);
v.setLabelProvider(new LabelProvider());
v.setContentProvider(new ArrayContentProvider());
v.setInput(new String[]{"value 1", "value 2"});
return v;
}
public static void main(final String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setSize(200, 60);
shell.setLayout(new GridLayout());
final ComboViewer v = createViewer(shell);
// This wires up the userSelectedSomething method correctly
v.addSelectionChangedListener(new ISelectionChangedListener() {
#Override
public void selectionChanged(final SelectionChangedEvent event) {
userSelectedSomething();
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
public static void userSelectedSomething() {
// This should be called *only if* the user selected from the drop-down
}
public static void userTypedSomething() {
// This should be called *only if* the user typed in the combo
}
I want to call the userTypedSomething method only if the user typed into the combo (and not when they selected from the drop-down). What listener should I add to achieve this? Adding a modify listener to the combo viewer with v.getCombo().addModifyListener(...) is no good as this is triggered for both typing and selection from the combo.
private static ComboViewer createViewer(final Shell shell) {
final ComboViewer v = new ComboViewer(shell, SWT.DROP_DOWN);
v.setLabelProvider(new LabelProvider());
v.setContentProvider(new ArrayContentProvider());
v.setInput(new String[]{"value 1", "value 2"});
return v;
}
private static boolean userTyped;
private static int index = -1;
public static void main(final String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setSize(200, 60);
shell.setLayout(new GridLayout());
final ComboViewer v = createViewer(shell);
/*
* invoked multiple times when combo selection happens
* invoked once when user types
*/
v.getCombo().addVerifyListener(new VerifyListener() {
#Override
public void verifyText(VerifyEvent e) {
userTyped = (e.keyCode != 0);
}
});
v.getCombo().addModifyListener(new ModifyListener() {
#Override
public void modifyText(ModifyEvent e) {
Combo c = (Combo)e.widget;
if(userTyped || index == c.getSelectionIndex() || c.getSelectionIndex() == -1)
{
userTypedOrEditedSomething();
}
index = c.getSelectionIndex();
}
});
// This wires up the userSelectedSomething method correctly
v.addSelectionChangedListener(new ISelectionChangedListener() {
#Override
public void selectionChanged(final SelectionChangedEvent event) {
userSelectedSomething();
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
public static void userSelectedSomething() {
// This should be called *only if* the user selected from the drop-down
System.out.println("User selected");
}
public static void userTypedOrEditedSomething() {
// This should be called *only if* the user typed in the combo
System.out.println("User typed or edited");
}
I would suggest you to use Verify event instead Key UP as you might endup handling lot of things (arrow keys, magic keys...etc). Verify is also Key Event but it filter out ALT,CNTRL,SHIFT combination. When user types just check for keycode!=0.
As you pointed out, when you use CNTRL+V ,Right click Menu paste....combo doesn't consider it as key event but it fires verify event to make sure the clipboard text is valid for combo or not. I think this is how it should work as Menu item selection and Key event on combo are different things.
you can always monitor all key events for special actions like copy/paste/delete.
the above sample code should be able to perform what you are looking for.
Since you want to listen to keyboard input, I would suggest listening to SWT.KeyUp.
This should be a good starting point:
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final Combo combo = new Combo(shell, SWT.NONE);
combo.add("First");
combo.add("Second");
combo.addListener(SWT.Selection, new Listener() {
#Override
public void handleEvent(Event arg0) {
System.out.println("Selected: " + combo.getItem(combo.getSelectionIndex()));
}
});
combo.addListener(SWT.KeyUp, new Listener() {
#Override
public void handleEvent(Event arg0) {
System.out.println("Typed");
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
I have a little control-panel, just a little application that I made. I would like to minimize/put the control-panel up/down with the systemicons, together with battery life, date, networks etc.
Anyone that can give me a clue, link to a tutorial or something to read?
As of Java 6, this is supported in the SystemTray and TrayIcon classes. SystemTray has a pretty extensive example in its Javadocs:
TrayIcon trayIcon = null;
if (SystemTray.isSupported()) {
// get the SystemTray instance
SystemTray tray = SystemTray.getSystemTray();
// load an image
Image image = Toolkit.getDefaultToolkit().getImage("your_image/path_here.gif");
// create a action listener to listen for default action executed on the tray icon
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 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(...);
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);
}
// ...
You could also check out this article, or this tech tip.
It's very simple
import java.awt.*;
import java.awt.event.*;
import javax.swing.JOptionPane;
public class SystemTrayDemo{
//start of main method
public static void main(String []args){
//checking for support
if(!SystemTray.isSupported()){
System.out.println("System tray is not supported !!! ");
return ;
}
//get the systemTray of the system
SystemTray systemTray = SystemTray.getSystemTray();
//get default toolkit
//Toolkit toolkit = Toolkit.getDefaultToolkit();
//get image
//Toolkit.getDefaultToolkit().getImage("src/resources/busylogo.jpg");
Image image = Toolkit.getDefaultToolkit().getImage("src/images/1.gif");
//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
}//end of class
Set appropriate path for image and then run the program. t.y. :)
This is the code you can use to access and customize the system tray:
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 Performed!",
TrayIcon.MessageType.INFO);
}
};
trayIcon.setImageAutoSize(true);
trayIcon.addActionListener(actionListener);
trayIcon.addMouseListener(mouseListener);
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.err.println("TrayIcon could not be added.");
}
} else {
// System Tray is not supported
}