I have a Java application that reduce into the system tray when the red cross is pressed.
Whenever this happen, I display a message to inform the user that the application is still running in the system tray.
Here's the code for that :
...
#Override
public void windowClosing(WindowEvent e) {
try {
tray.add(trayIcon);
trayIcon.displayMessage("", "The application has been reduced
in the system tray, to stop it, press the \"Quit\" button",
TrayIcon.MessageType.WARNING);
setVisible(false);
} catch (AWTException ex) {
System.out.println("unable to add to tray");
}
}
...
For the moment, the message disappears if the user clicks on it.
I would like to set up a counter so the message would fade out after a couple of seconds even if nothing has been done.
Does anyone know a nice way to do it cause I can't seem to find any existing method for that.
EDIT
I have to correct my question, in fact, after testing it a little bit longer, it automatically fades out after, let's say, 7-8 seconds but I find it a little bit too long. Also, it only disappears if the user is executing an action (moving the mouse or typing on the keyboard)
So the new question would be : Is there a way to reduce the fade out time and change the message behaviour by configuring the Java application or is it inherent to Windows?
So the new question would be : Is there a way to reduce the fade out
time by configuring the Java application or is it inherent to Windows?
MSDN says in part How long to notify - In Windows Vista and later, notifications are displayed for a fixed duration of 9 seconds.
any changes is possible to maintain only on Windows size, but seems like is valid/applied for all messagess
you can to create own Traslucent JDialog (Transparency could be way too) placed programatically to the left bottom, fading out will be invoked from Swing Timer
Related
I am using java.awt.SystemTray to create and manage the tray icon and balloon messages. Everything works fine.
But I would like to know whether it is possible to close or fade the message after it is displayed.
Right now, the user needs to click the balloon or close it, otherwise the message will not go away.
I'm not sure about other platforms, but on Windows, the message will only disappear if the machine is in use - i.e. if the user is typing something or moving the mouse. If you don't move the mouse or type anything, the message will stay where it is.
The following code shows a message for me. If I move the mouse, it disappears about 5 seconds later. If I don't, it stays around until such time as I move the mouse or type something, at which point it disappears.
final TrayIcon ti = new TrayIcon(XTPSkin.getInstance().getAppIcon().getImage());
final SystemTray st = SystemTray.getSystemTray();
st.add(ti);
ti.displayMessage("foo", "bar", MessageType.INFO);
There's no direct way to remove the message before its time is up - however, you can remove the TrayIcon (and if necessary immediately re-add it, although this really isn't recommended). Removing the TrayIcon causes the message to also be removed.
The following code, added to the above, causes the TrayIcon and the message to both be removed:
SwingUtilities.invokeLater(new Runnable(){
public void run() {
try {
Thread.sleep(1000); // Don't do this
st.remove(ti);
} catch (InterruptedException ie) {
// You won't need this when the sleep is removed
}
}
});
Notes:
You need to wrap the first block of code above with some exception handling for AWTException
The Thread.sleep in the second block is strictly for demonstration purposes. Since this code will execute on the AWT thread, you should not include that sleep in actual code.
Continually removing and re-adding the TrayIcon in this way is probably a bad idea. Since the message does disappear if the user is using the machine, it's probably wisest not to do this.
Is it possible to listen for key and mouse events without having a gui selected by the user? I want to make a program that runs in the background without a gui and responds to user interaction such as pressing ctrl-t.
The window manger will track the focus and direct input according to its configuration. If your window manager decides to send input to a different program because it is enforcing a change of focus, you are out of luck.
While the program lacks focus, if it were able to obtain the mouse and keyboard events, it would be a major security hole. Basically any small unnoticeable background program could spy on the entire system, possibly even stealing passwords in the process.
Your only hope is to find an option in your window manager which will allow you to minimize the program without changing focus. Of course, whatever you type will only go the minimized program (and not affect the rest of the system).
Another technique (by no means guaranteed) is for the program to detect minimization events, and to request focus within a minimization event handler. Note that doing so would probably (If I were writing a window manager) unminimize the window.
You probably would like to look at jnativehook.
Jnativehook allows you to listen for keyboard events using JNA without an existing focused GUI.
https://github.com/chrislgarry/Apollo-11
https://github.com/kwhat/jnativehook/blob/2.2/doc/ConsumingEvents.md
Example usage:
try {
GlobalScreen.registerNativeHook()
} catch (NativeHookException ex) {
System.out.println(ex.message)
}
GlobalScreen.addNativeKeyListener(
new NativeKeyListener() {
#Override
public void nativeKeyTyped(NativeKeyEvent nativeEvent) {
System.out.println("Pressed " + nativeEvent.keyChar)
}
}
)
Right now I have a frame in full screen exclusive mode, which commands the whole screen. The panel has a button which launches the windows native calculator program (just for testing purposes). Is it possible to have that process start completely in the background? Right now I have this:
this.parent.setAlwaysOnTop(true);
try {
Process p = Runtime.getRuntime().exec("calc");
} catch (IOException e1) {
ErrorDialog error = new ErrorDialog("Error handling your shell action");
e1.printStackTrace();
System.exit(0);
}
this.parent.setAlwaysOnTop(false);
This DOES do what I need, but doesn't make it pretty. It "minimizes" my window first, then starts calc, then re-maximizes my window. It all happens quickly but stuff is flashing all over the place. Is it possible to make "calc" run in the background without touching my main window and making it completely seamless?
This is in principle a window manager specific thing, at least on X systems (like Linux and most other Unixes with a GUI).
Some window managers start new programs always in the background, always in the foreground, or even require the user to draw the window's area with the mouse. Others respect the wishes of the program being started.
Thus, you could have a look at the command line options of the program you are starting, maybe they have an option like "start minimized" or similar.
If you are using KDE (and the KDE window manager), you can use kstart --onbottom ... or kstart --minimize ... to start your program, which will put the window on the bottom of the stack, or start it minimized. (Have a look at the kstart options, you'll also want to use --window or --windowclass to indicate the window.)
Test it out in Linux, maybe it doesn't flicker there. If not many people will use it in Windows, flickering shouldn't be a big concern.
I don't think there's a Java-specific way to handle this, you're launching an external process. How it launches is up to the OS.
In my Swing application, I'm using a custom module to record a screen cast.
However, I'm a bit hung up on when to force the recording to stop. Right now, I check to see if the user still wishes to record (meaning that they haven't clicked the 'stop' button) and if the application is still open (closing the application causes the recording to stop gracefully).
The problem is that the recording will continue if the application gets pushed behind other apps or minimized, causing recording of 'junk'. I need the recording to stop when the application is no longer 'on top' of the screen. Using the application's focus doesn't seem to work due to other dialogs and things popping up.
Suggestions?
You may want to try adding a WindowListener and override the windowDeactivated() event, which should get called when the frame is no longer the "active window" according to the operating system.
UPDATE:
If you are conscientious about making sure that your child dialogs and windows are owned by your application (making sure you pass in your application frame as the owner), then you could make your WindowListener do something like this:
public void windowDeactivated(WindowEvent e) {
if(e.getOppositeWindow() == null){
// will be null when another application window gets activated, stop recording
}
for(Window w : appFrame.getOwnedWindows()){
if(w.equals(e.getOppositeWindow())){
// one of the windows owned by the frame is active, don't stop recording
}
}
}
Then you will be able to determine if the window focus has left your application altogether or if the focus has just changed to a different child window/dialog.
I want to pop up a dialog box that says "Saving..." and once the operation is completed, it simply disappears. While the saving is in progress, I dont want the user to be able to do anything. I also dont want an OK button.
What is the name of the Java class that allows me to do this?
I think JDialog is what you want - be sure to call setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE) on it since unlike a JFrame, its default behaviour is HIDE_ON_CLOSE.
Here's the final code I found that roughly simulated what I wanted to do:
// Create dialog box
JDialog dialog = new JDialog(new JFrame(), "Saving...");
// IMPORTANT: setLocationRelativeTo(null) is called AFTER you setSize()
// otherwise, your dialog box will not be at the center of the screen!
dialog.setSize(200,200);
dialog.setLocationRelativeTo(null);
dialog.toFront(); // raise above other java windows
dialog.setVisible(true);
// Sleep for 2 seconds
try
{
Thread.sleep(2000);
} catch (InterruptedException ex)
{
Logger.getLogger(JavaDialogBox.class.getName()).log(Level.SEVERE, null, ex);
}
// Then "close" the dialog box
dialog.dispose();
Lastly, found these 3 links to be quite helpful when writing the above code:
Center the dialog to screen
How to create JDialog
How to pause execution
You might also consider using a javax.swing.JProgressBar within your dialog so you can show progress is happening. If you have enough information during the save process to give a percentage complete you can show that, and if not you can show it as indeterminate (moving back and forth until complete). Then dispose the dialog once the save process is complete -- this would be nice user experience enhancement over showing a static text message for a fixed amount of time. Here's a tutorial with demo Java code showing an example dialog: http://java.sun.com/docs/books/tutorial/uiswing/components/progress.html.
I think what you may want is a modal JDialog. They make it fairly easy to block user interaction for your whole application and you have some extra control.
The code snippet you posted will potentially have issues if your save operation takes longer than 2 seconds. I'd suggest calling your save() function in the place where you currently have the Thread.sleep(). That way, you know that no matter how long the save takes, the UI will be blocked.