I use JComponent.setToolTipText to get tooltips in my java application, but unlike, e.g., eclipse, if I switch to another application when a tip is showing, it remains hovering over what I'm doing until I switch back to the java app and move the mouse around to get it off the element before returning to the alternate application. Is there a way to make the tooltips in my app better citizens? to make them disappear when the app loses focus?
I'm on a mac if relevant.
I've found a solution! (with some input from a colleague)
<myJFrame>.addWindowFocusListener(new WindowFocusListener() {
#Override #SuppressWarnings("unused")
public void windowLostFocus(WindowEvent e) {
ToolTipManager.sharedInstance().setEnabled(false);
}
#Override #SuppressWarnings("unused")
public void windowGainedFocus(WindowEvent e) {
ToolTipManager.sharedInstance().setEnabled(true);
}
});
A WindowAdapter listening to windowActivated/Deactivated also works.
A plain FocusListener does not.
Related
I have started implementing JCEF in a project of mine, and I am initializing the embedded browser in a JInternalFrame inside of a JFrame, alongside a series of form fields on a JPanel next to the JInternalFrame. The browser component doesn't fully initialize until the JFrame actually becomes visible, and I'm finding that my JTextFields are uneditable unless the JFrame loses and regains focus.
Any idea of what could be happening and how to fix it? This only happens when using a JInternalFrame with the JCEF component...
It also happens every time I call loadURL to load a new page in the browser: the JTextFields become uneditable again, until I lose/gain focus in the JFrame.
UPDATE:
I have found a hack which allows the JTextFields to become editable again, but I wouldn't call it a solution because it is not very elegant. I added a load handler to the CefClient instance ( client.addLoadHandler(new CefLoadHandlerAdapter()) ) with an #Ovveride on the onLoadingStateChange method, which in turn gives access to the current browser component. From there I can detect when loading in the browser is complete, and use SwingUtilities to get the Window that the browser component is in. Then I setVisible(false) and setVisible(true) on that Window. I say it's not a solution because every time the browser is done loading the Window disappears and reappears. Even though the JTextFields are editable again, it is quite ugly to see the window flashing. I've tried all kinds of revalidate() and repaint() methods to no avail, unless I didn't call them right...
client.addLoadHandler(new CefLoadHandlerAdapter() {
#Override
public void onLoadingStateChange(CefBrowser browser, boolean isLoading,
boolean canGoBack, boolean canGoForward) {
if (!isLoading) {
//browser_ready = true;
System.out.println("Browser has finished loading!");
SwingUtilities.windowForComponent( browser.getUIComponent() ).setVisible(false);
SwingUtilities.windowForComponent( browser.getUIComponent() ).setVisible(true);
}
}
});
If anyone can suggest a better solution, please do!
I figured out the problem by studying the sample JCEF application a little better. I need to implement a FocusHandler in order to release the embedded browser's hold on keyboard input:
private boolean browserFocus_ = true;
---
jTextField1.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
if (!browserFocus_) return;
browserFocus_ = false;
KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
jTextField1.requestFocus();
}
});
I have been wondering multiple times over the past why some of my Java/Swing popup menus seem to work under Linux but not under Windows and vice versa. So how do I implement a popup menu that works on both OS'es?
Read the section from the Swing tutorial on Bringing Up a Popup Menu for working examples.
It shows how to use the isPopupTrigger() method of the MouseEvent.
Or you can use the setComponentPopupMenu(...) method of JComponent which has been around since JDK 1.5 and you don't have to worry about the MouseListener.
In Windows, a call to MouseEvent::isPopupTrigger will work fine in the mouseReleased method, but returns always false when called from within the mousePressed method. In Linux, the opposite is the case.
#Override
public void mousePressed(MouseEvent e)
{
checkPopup(e); // triggers the popup event under Linux but not under Windows
}
#Override
public void mouseReleased(MouseEvent e)
{
checkPopup(e); // triggers the popup event under Windows but not under Linux
}
private void checkPopup(MouseEvent e)
{
if (e.isPopupTrigger())
{
// do something
}
}
I wrote earlier about the following problem and received an answer to use either Splash Screen or JDialog. As I was researching about the above 2 solutions, now I think that I might be able to solve my problem by using another applet.
The problem: Before my main applet GUI runs I need to download certain files to local PC for the GUI to work. Therefore, I am now thinking of having 2 applets where Applet1 downloads the files, Applet2 is the main GUI.
I would use the Splash Screen or JDialog but at the moment they don't seem to be what I need. How can I invoke Applet2 from Applet1 automatically in the same window, and fully close Applet1 once Applet1 is done downloading files? Is the Applet idea better solution for my problem than Splash Screen or JDialog?
Here is the code of my main applet (in this case it would be Applet2):
#Override
public void init() {
/* Create and display the Applet2 once Applet1 is done */
try {
java.awt.EventQueue.invokeAndWait(new Runnable() {
#Override
public void run() {
initComponents();//Draw the GUI
}
});
} catch (Exception ex) {}
}
My earilier post:
Java - Pause initComponents from running?
I have a kiosk GUI application I'm working on and it requires me to block users from being able to Alt-Tab out of the fullscreen window. I posted a question about this a while back and a member helped me with some code, which worked perfectly under a Windows environment.
Here it is:
public class TabStopper implements Runnable {
private boolean isWorking = false;
private MenuFrame parent;
public TabStopper(MenuFrame parent) {
this.parent = parent;
new Thread(this, "TabStopper").start();
}
public void run() {
this.isWorking = true;
Robot robot;
try {
robot = new Robot();
while (isWorking) {
robot.keyRelease(KeyEvent.VK_ALT);
robot.keyRelease(KeyEvent.VK_TAB);
parent.requestFocus();
Thread.sleep(10);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void stop() {
this.isWorking = false;
}
public boolean isWorking() {
return this.isWorking;
}
}
However, I need this to be able to work in Linux as well. I made an executable jar from the source and brought it into Linux. Everything worked except the Alt and Tab keys were being constantly pressed. The buttons on my GUI were constantly being cycled and I was able to open a terminal (I set a backdoor in the application during testing in case something like this happens) which wouldn't let me type anything because Tab lists all the files in the current directory.
Could anyone tell me if there would be a fix that would work in both Linux and Windows environments. However, if I had to choose, I would go for Linux.
EDIT: I can also confirm that the Alt key is being "pressed". What's with this weird behaviour?
Forget grabbing Alt+Tab with hacks like this. It is a bad hack and it is error-prone. There are also so many other hotkey combinations.
For linux you have two options:
Use a minimal window manager or no window manager at all. For example, with fluxbox you can remove all key bindings alltogether and you can also make your application maximise by default, etc. You can empty the desktop menus such that the user gains no control even when your application crashes. This is a clean solution that really solves your problem instead of some parts of it. There are many ways to fiddle with the system other than Alt+Tab.
Grab input controls completely. This is what games do. For example libSDL does it for you and there are java wrappers for the functionality as well. This should also work as expected, except you use a window manager that does not allow input control grabbing per default (I don't know of any).
I have a Java/Swing desktop application (Java 6u16 on Windows XP) which occasionally appears to the users to hang. I say appears to because in reality what is happening is that the application is showing a modal dialog but this dialog is not being rendered. If the user uses Alt-Tab to switch away from the application and then subsequently returns to it, the dialog gets rendered correctly. Additionally, if a remote user connects to the session via NetOp (a VNC/Remote Desktop workalike) this also causes the GUI to be redrawn correctly.
The app runs via JavaWebstart. Since I've heard of rendering issues being caused by DirectDraw, I added the following to the JNLP
<property name="sun.java2d.noddraw" value="true"/>
but the problem still occurs (If I have understood correctly, this will switch off DirectDraw and Direct3d completely: see http://download.oracle.com/javase/1.5.0/docs/guide/2d/flags.html#noddraw)
I'm out of ideas on this one, any suggestions would be greatly appreciated.
Thanks,
Phil
Edit...
I have an abstract dialog class which extends JDialog and which all other dialogs extend. It contains the following method:
public void showDialog() {
initKeyBindings();
Application.getApplication().deactivateScannerListener();
setVisible(true);
}
Whenever I want to display a dialog, I call showDialog(). The initKeyBindings method sets up an ActionMap while the second line is application specific (Application is a singleton, I'm disabling the JPOS scanner listener while the dialog is displaying).
There is a corresponding hideDialog() method as follows:
public void hideDialog() {
setVisible(false);
Application.getApplication().activateScannerListener();
dispose();
}
Thanks,
Phil
Edit...
Sorry about this, one more edit: all of the dialogs have a parent. The AbstractDialog class will default to the main application frame if no other parent is specified.
FYI
For anyone following this, I've added the following to my code:
if (SwingUtilities.isEventDispatchThread()) {
initialiseAndShowDialog();
} else {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
initialiseAndShowDialog();
}
});
}
This ensures that the dialog is only opened from the EDT.
Which thread are you calling showDialog() from? Swing components should be accessed on the Event Dispatch Thread only.
You could try SwingUtilities.invokeAndWait()
and the Runnable argument passed to it should call showDialog().
Let us know if it fixed the problem.