My app is a JApplet which opens a JFrame. the applet has a listener and a button, so that if the frame goes behind another window (looses focus), the user can simply click the button to get it to come to the front. frame.toFront(); This works fine.
But initially (in the applet's public void init() {}),
after calling frame.setVisible(true); I call frame.toFront(); to to make sure it starts in front. However, the frame then immediately goes behind the browser. Pressing the button calls it back, though.
I have tried a running a separate thread which repeatedly calls frame.toFront(); But as soon as this stops, the frame goes behind the browser anyways. Only when the button is pressed does it come to the front, and stay in front. Also, having a loop or time continually holding it in front is not a good option, because the user may need or want to have it go behind on purpose.
This "bug" is not present on the Mac (which runs Java 1.5), but on Windows (running 1.6) - including IE, FF, Chrome, Safari, but not Opera (strangely).
Possible cause and fix?
Have you tried setAlwaysOnTop(true) on the frame? I'm not sure however, if this is allowed on frames or windows created from an applet.
The setAlwaysOnTop(true) solves one problem, but create another, namely that now there is no way for the user to actually send the window to the back.
My sollution is a hack:
In the WindowListener attached to the JFrame, place this code:
#Override
public void windowDeactivated(WindowEvent e)
{
if(firstToBack) //firstToBack is an bloolean instance variable initialized to true
{
final JFrame f = frame;
new Thread() { public void run() {
try { Thread.sleep(300); } catch(InterruptedException ie) {}
f.toFront();
}}.start();
firstToBack = false;
}
}
This basically starts a new Thread first time, which waits a little and then calls the JFrame to the front. It only executes once, so the frame doesn't keep coming to the front every time the user sends it to the back. The 300 milliseconds is an arbitrary amount of time and perhaps not even necessary.
Perhaps someone can tell me why this works, but when the same kind of thread was started fron the applet's init() method, the window went to the back anyways, after the thread ended?
Related
I have a strange issue with our application that only manifests itself in java7, everything worked flawlessy in java6.
I have a product-choosing JDialog that has a JTable, an ok button, a cancel button, a jtextfield for searching and a jcheckbox "keep window open".
The idea is, that if "keep window open" is selected, then a press to the ok button will not dispose the jdialog, but instead set a reopen-variable to true, and call setVisible(false).
Then I have the following code to reopen it:
while(SelectionDialog.isReopen()){
Product p1 = SelectionDialog.reopen();
if (p1 == null) return;
//Do stuff with product
}
In SelectionDialog:
public static SelectionDialog reopen = null; //Is instanciated to current jdialog if ok button is pressed and reopen-checkbox is selected. setvisible(false) is then called instead of dispose()
public static Product reopen() {
SelectionDialog.reopen.setVisible(true);
return SelectionDialog.returnedData;
}
The strange thing is, that when the JDialog is redisplayed, the jtextfield is not focusable/clickable. Everything else seems ok. If I then press the ok button and it reopens, the jtextfield is ok again, but if I press ok another time it is not focusable/clickable again.
The jtextfield displays text, but there is no blinking cursor when it does not work.So every other time the jtextfield simply doesn't work, and every other time it works.
All these methods return true for the jtextfield: isEnabled, isEditable, isDisplayable, isVisible, isFocusable, isOpaque, isShowing, isValid.
Calling updateUI on jtextfield in swingutilities.invokelater before setVisible(true) on jdialog does not solve the problem. Neither does requestfocusinwindow.
The only thing that seems to work to bring the jtextfield back from the dead is switching to another program, and then switching back to my java-program.
I have tested, and the problem persists in both jdk1.7.0_03 and 1.7.0_51.
I don't have this problem in java6 and before.
What can be causing the problem? (I have removed everything from "//Do stuff with product" in case this did something, but the problem persists).
And even if you don't know what causes the problem, does anyone have any suggestions to a workaround that may work?
UPDATE:
Thanx to MadProgrammers comments, it now works with the following code:
SwingUtilities.invokeLater(new ReopenProductList()); //Instead of while-loop
private class ReopenProductList implements Runnable{
public void run(){
if (SelectionDialog.isReopen()){
Product p1 = SelectionDialog.reopen();
if (p1 == null) return;
//Do stuff with product
SwingUtilities.invokeLater(new ReopenProductList());
}
}
}
Based on the description of the problem, it would appear that you are blocking the Event Dispatching Thread by using the while loop.
Having had a situation when testing Java 7 early on (it actually deadlocked on SwingUtiltiies.invokeLater). We never found the fault, as we re-wrote the entire action of code (the original was funky), it would suggest that the threading model,has changed between Java 6 & 7.
Try removing the while loop from the EDT
I have multiple JDialogs in my application stored in a map. These JDialogs are all have
setModel(false);
When these dialogs are out of focus and I want to bring a specific JDialog toFront all JDialogs come toFront. I want the specific Jdialog to come to front and want the other JDialogs to remain in back.
HashMap<String, JDialog> jDialogMap = getJDialogMap();
String key = "jd1";
JDialog specificJDialog= jDialogMap.get(key);
if (specificJDialog== null){
specificJDialog= new JDialog();
specificJDialog.setModel(false);
specificJDialog.setVisible(true);
jDialogMap.put("jd2", specificJDialog);
} else {
specificJDialog.toFront();
return;
}
This code brings all the JDialogs toFront having the specificJDialog on top of the stack.
getJDialogMap();
This Method only returns a HashMap nothing else.
use requiredDialogObject.requestFocusInWindow();
whenever u need focus on the specific dialog
I found a solution to my problem I think it is worth sharing it.
Solution: Creating multiple JDilogs in an application with default constructor i.e. new JDialog() will result in a shared frame as the parent of each JDialog which will cause these kind of problems. So I used the overloaded constructor new JDialog(new JFrame()) to have separate parent for each JDialog and that solved my problem.
Had a similar issue. After opening the JDialog my main application window just requested the focus again, moving the JDialog window to the background, which was annoying. I experimented with modal() and toFront() methods, which both didn't work out for me, since modal() just prevented user interaction completely (outside of that JDialog) and toFront() also has effect on windows outside my application (by using it inside of a timer method, see below).
To keep the window in front of the main application I used a timer method, which was fired every 300 ms and just keeps requesting the focus by using the requestFocus() method.
import javax.swing.Timer;
Timer timer = new Timer(300, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
requestFocus();
}
});
timer.start();
I have an application that uses a JTabbedPane to show several different tabs. One of these tabs has a thread running to display it's contents. I have already implemented a ComponentListener to stop the thread when the tab is not visible. I can see the thread becoming active when the tab is selected and stopping when becoming invisible, quite as expected.
If I close my application when the tab with the thread is not selected, everything goes well and the application closes. If I close my application when the tab with the thread is visible, the tab does not receive a ComponentEvent, so the thread stays active and I need to kill the application by hand (using the Terminate button on the console in Eclipse).
I prefer not to use the System.exit() method to close my application, but rather stop all threads and dispose all windows. This is working like a charm, except for this one tab with it's thread.
I have already tried to set the JTabbedPane to invisible before disposing my window, or removeAll(). Neither had the expected result. The removeAll() even had the opposite result. If the tab was not active, it would receive a ComponentEvent to indicate that is had become visible (componentShown) (actually, all tabs would receive the event in turn, but none would get a componentHidden).
Obviously, the thread should be stopped both when I close the window via the file menu (over which I have some control and where I have tested the removeAll and setVisible(false) methods) as well as when the window is disposed because the user clicks on the cross in the window corner.
Update
I have found a way to make the thread that seems to cause the problem run as daemon thread as suggested. This has however led to an unexpected problem. The class that started the problematic thread was the VisRunner class from the JUNG software package I am using. It contains a method "relax" in which the thread is started.
#Override
public void relax() {
// in case its running
stop();
stop = false;
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
I have created the MyVisRunner class:
import edu.uci.ics.jung.algorithms.layout.util.VisRunner;
import edu.uci.ics.jung.algorithms.util.IterativeContext;
public class MyVisRunner extends VisRunner {
public MyVisRunner(final IterativeContext process) {
super(process);
}
#Override
public void relax() {
// in case it's running
Log.d("Relaxing");
stop();
stop = false;
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.setDaemon(true);
thread.start();
}
}
I load the relaxer as such:
visModel = new DefaultVisualizationModel<>(layout);
visModel.setRelaxer(new MyVisRunner(layout));
I would have expected this to solve the problem, but it only increases the problem. When I now start my software, it will not stop, even when the problematic tab is not even visible (the tab is constructed, but is not visible). The relax method from MyVisRunner has not even been called in that case; the thread is not initialized anywhere else in the VisRunner class. Commenting out the setRelaxer line will solve this additional problem (obviously keeping the original problem).
Update 2
I have solved the problem finally. I didn't realize that when I set my own relaxer, there was already a relaxer running. I have adjusted the code to:
visModel = new DefaultVisualizationModel<>(layout);
visModel.getRelaxer().stop();
visModel.setRelaxer(new MyVisRunner(layout));
This has solved both the additional problem as well as my original one.
You should set the thread as a daemon thread:
myThread.setDaemon(true);
A Virtual Machine will terminate if there are no more running non-daemon threads.
BTW you can add a WindowListener on your JFrame for windowClosing events.
What happens when you minimize JInternalFrame object using built-in icon located in the corner (next to maximizing and closing ones)?
I have a JInternalFrame in JDesktopPane and my problem is following:
When I minimize one frame it is being minimized. When I try to re-open the frame via using JMenu it works for first time. When I do this procedure again, the frame is being minimized but not re-opened, but when I click manually on a iconified frame, it shows properly.
I tried to do combination of setSelected, moveToFront, setIcon, setVisible, activateFrame, or requestFocus, but still no effects.
I wonder what happens when you minimize JInternalFrame, what is being set, what should do to get focus of a particular frame, and why the procedure it works for the first time and not others?
thanks
Seems to work fine for me
try {
if (myFrame.isIcon()) {
myFrame.setIcon(false);
miDoShowHide.setText("Hide");
} else {
myFrame.setIcon(true);
miDoShowHide.setText("Show");
}
} catch (Exception exp) {
exp.printStackTrace();
}
I set up a menu item that would call this functionality. I tested by using the menu to min, restore, min, restore. I minimized the frame by the frame control and restored via the menu, minimized by the menu and restored by the frame control.
Also make sure that the JInternalFrame is set to Iconifiable (setIconifiable(true)) otherwise you will experience some strange results
I know this is sort of a vague question, but I will try to make it as clear as possible. When my Java app launches for the first time, it does some checking to see if files and directories exist and checks for an internet connection.
The app then allows the user to move on to the dashboard, which requires loading and adding many Swing components to the Background Panel. This takes time.
I was wondering how I could make it so that during the loading process at the start, the app loads all of the Swing components Images etc. so that they appear instantly when the user executes the command to do so.
I can load all of the components like this:
JButton = new JButton("blah");
but I'm not sure that's enough to make the components appear instantly, wouldn't adding several image filled Swing components at the same time still lag the UI thread, even if it was already "loaded" as seen above?
Thanks!
on the components use
setVisible(false)
for example
public class myParentPanel extends JPanel{
public myParentPanel{
//add all the child components
//Do what ever takes along time
setVisible(false); //this then makes in invisible but still
//allows all the set up code to run
}
public void showParent(){
setVisible(true);
invalidate();
}
}
and then create a method to make them visible when required. Hence all your setting in the constructors ca be called then when you call your method say:
drawWindow()
it then only has to call setVisible(true) and invalidate the screen to call their painting methods :).
An advancement on this would be to *run your setups i.e your checking and loading the panels methods on a separate threads*so you don't have to wait for a sequential loading. So on your loading you may to use an anonymous class
SwingUtilities.invokeLater(new Runnable(){ public void run(){
//do my display set up
}});