Programmatically close Java Tray Balloon - java

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.

Related

Ensure that AWT Canvas is drawn on-screen before doing something else

In my application I NEED to make sure that Canvas is actually appeared on the screen before going for the next step. The reason is that I need to retrieve an AWT Drawable - i.e. the native window surface of that canvas. And that drawable would be invalid if the canvas is not visible, even if it has the flag "visible" set to true.
The problem Im having is that I can't be sure when Java actually decides to display it.
I even made a code to actually delay after Canvas constructor, but what happens is that it is displayed AFTER the delay has expired.
canvas3d = new Canvas3d();
System.err.println("Before sleep");
try
{
Thread.sleep(3000);
}
catch (Exception e) {}
System.err.println("After sleep");
canvas3d.Init();
This is odd, because the drawing and rendering of elements should be handled by a completely separate thread, and my main thread sleeping should theoretically give it enough time to process the stuff. But it still waits for some reason.
Adding Repaint() or revalidate() doesn't help.
The problem with this is that sometimes, the canvas gets displayed before the Init() gets to the point that it needs it to be visible. But other times - it doesn't get displayed before that.
Can I somehow FORCE the application to display the element before I'm doing anything else? Or can I somehow retrieve if the canvas is displayed at the moment or not? Because checking Canvas.visible is pointless - whether it's true or false, it doesn't mean that it's actually displayed or hidden in that precise moment during runtime. It's just a flag showing that it's supposed to be displayed, but oh, oopsie, Java just can't guarantee that it actually is!
It seems that I can use canvas.isShowing() to test if it's actually visible on the screen. At least by checking that parameter I got the result I wanted (so far).
I am still not certain if that's enough and if there's something more that can go wrong on the low level, particularly if I try to access the surface during X11 rendering pipeline where AWT has already completely "displayed" the component but X11 hasn't yet finished drawing it on the screen.
That's one concern.
But for now, it seems to be the best answer I can come up with.

Disable Ctrl-alt-delete, alt-tab

I am creating a LOGIN form that will automatically show up whenever the computer starts up.
I got it right though. My problem is, I have to disable the ALT+TAB and CTRL+ALT+DEL keystrokes when my program is already running. But the thing is, whenever I test my program, my computer gets lag. Especially when I include the method of disabling ALT+TAB.
Somebody HELP!
public void altTab ()
{
try{
Robot robot = new Robot();
while(true){
robot.keyRelease(KeyEvent.VK_ALT);
robot.keyRelease(KeyEvent.VK_TAB);
this.requestFocus(true);
}
}catch(Exception e){
}
You get lag because of having an endless loop running again and again. Try putting an event on Key down and cancel it?(or release it)
You cant disable Alt+Ctrl+Del nor can you call it via your Robot class (using keypress or keyrelease - you can try it). And I don't think the code inside your while loop will run always- you are just releasing the key pressed. I am not sure about this, but you might try event handlers...
Inside that loop, you should call Thread.sleep(). Take a look at this answer, which shares much of the same code you used:
https://stackoverflow.com/a/6128105/2579661

How to get Java's TrayIcon message to fade out?

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

Using a JFrame's focus (being lost) to stop recording a screen cast?

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.

How to implement "Saving..." dialog box in Java?

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.

Categories