0

My users like having multiple JFrames; it allows them to resize the different components and place them wherever they want on the screen. However, I have a request to make all the child windows come to the front together... in other words, lets say they maximize another window in front of all the windows, and then use the task bar to click on just one of the JFrames. How can I set it so that they all come to the front? Note: it is also possible to close the child windows; if they are actually hidden, I do not want them to come to the front. I have a class ApplicationModel that keeps track of whether a window is hidden or not.

Things I've tried:

  1. Using windowActivated() and focusGained() to try to bring them all to the front. This usually results in an infinite loop. The problem is that my eventing framework sends these requests off the Event Dispatch Thread, so any sort of blocking with an AtomicBoolean doesn't last long enough.
    • The main problem is not that I can't make them come to the front... I have made them come to the front. The problem is that they KEEP trying to come to the front, as bringing a window to the front throws the focusGained and windowActivated events, which creates an endless loop...
  2. Making one window the master, and making the others a JDialog. Unfortunately, either the windows are modeless (and therefore don't come to front with the master window), or they are modal, (and therefore block the master window).

How can I fix either of these problems, or is there an entirely different third solution?

durron597
  • 31,968
  • 17
  • 99
  • 158
  • The problem is, technically, only one frame can be on top...how do you determine this? You want to take a look at [Frame.getFrames](http://docs.oracle.com/javase/7/docs/api/java/awt/Frame.html#getFrames()) for starters and [Window#toFront](http://docs.oracle.com/javase/7/docs/api/java/awt/Window.html#toFront()) – MadProgrammer Sep 25 '13 at 22:35
  • @MadProgrammer Well, the one they selected should be on TOP top, but the other windows should just be in front of any other windows in the system. Like, lets say they are running Microsoft word, they maximize it, then use the taskbar to click on one of my windows, only THAT window becomes visible. I don't much care what order they are on top in, except that the one they selected should be the very top. – durron597 Sep 25 '13 at 22:43
  • `2.Making one window the master, and making the others a JDialog.` - this should work. Just make sure the JFrame is the owner of the dialog. If it doesn't work then post your `SSCCE` that demonstrates the problem. – camickr Sep 26 '13 at 00:01
  • @camickr Fascinating, my sscce version of the dialog app works, but my real one does not. I'll have to investigate further why. – durron597 Sep 26 '13 at 13:22
  • That's why a `SSCCE` should be created for all questions. – camickr Sep 26 '13 at 14:04
  • @camickr I agree completely, but I spent an hour trying to figure out the differences between my app and the sscce and came up with nothing. Maybe I'll copy the project and try to make an sscce by deleting code... – durron597 Sep 27 '13 at 16:49

2 Answers2

0

You can use a boolean field as a flag to prevent the infinite loop:

private boolean movingAllFramesToFront;

public void windowActivated(WindowEvent event) {
    if (movingAllFramesToFront) {
        return;
    }

    movingAllFramesToFront = true;

    List<Frame> frames = getAllApplicationFrames();
    for (Frame frame : frames) {
        if (!applicationModel.isHidden(frame)) {
            frame.toFront();
        }
    }

    event.getWindow().toFront();
    event.getWindow().requestFocus();

    EventQueue.invokeLater(new Runnable() {
        public void run() {
            movingAllFramesToFront = false;
        }
    );
}

Another thing you can try is the new autoRequestFocus property introduced in Java 1.7. I have never tried using it, but here's my understanding of how it works:

public void windowActivated(WindowEvent event) {
    final List<Frame> frames = getAllApplicationFrames();

    for (Frame frame : frames) {
        if (!applicationModel.isHidden(frame)) {
            frame.setAutoRequestFocus(false);
            frame.toFront();
        }
    }

    EventQueue.invokeLater(new Runnable() {
        public void run() {
            for (Frame frame : frames) {
                if (!applicationModel.isHidden(frame)) {
                    frame.setAutoRequestFocus(true);
                }
            }
        }
    );
}
VGR
  • 40,506
  • 4
  • 48
  • 63
0

I have an application with a lot of windows and had a problem similar to yours. My workaround is:

@Override
    public void windowActivated(WindowEvent e) {
        if (e.getOppositeWindow() == null) {
            //front every window
        }
    }

First I created a class "SlveFrame" (Slve being the name of my app), a child of "JFrame".

public class SlveFrame extends JFrame implements WindowListener {
    static ArrayList<SlveFrame> frames = new ArrayList<SlveFrame>();

    public SlveFrame () {
         addWindowListener(this); / /to make JFrame fire WindowListener's method
    }

    / /... every method added from WindowListener
    @Override
    public void windowActivated(WindowEvent e) {
        if (e.getOppositeWindow() == null) { // return null if window is not from my (or Your) work
            for (SlveFrame frame : frames) { // if you have no idea what this is, look for "for each loop java" in google
                 frame.toFront();
            }
        }
    }

    /**
    * The use of SlveFrame is almost the same as Jframe
    */
    @Override
    public void setVisible (boolean b) {
        if (b) 
            frames.add(this);
        else
            frames.remove(this); // may raise an exception if you're not careful
        super.setVisible(b); //   or your window will simply not be visible.
    }

    @Override
    public void dispose () {
        frames.dispose(this) // may raise an exception you'll want to handle
   }
}


The trick being that WindowEvent.getOppositeWIndow() returns a Jframe if the JFrame (or child class) is from your own program, meaning that if you switch to another program or app (such as eclipse, Firefox or a text editor) then back to any of your windows, then a call to getOppositeWindow() will return a 'null'. A simple if (e.getOppositeWindow()) makes it fairly easy to determine whether your window gain focus in condition that would require you to bring every window to the front, or rather to let everything be.

The overriding of setVisible (boolean b) and dispose () are optional but allow the dev to use it as a regular window.


I hope i could be of some help. Sincerly ~a lama

Prune
  • 76,765
  • 14
  • 60
  • 81
NRagot
  • 113
  • 2
  • 12
  • @Prune thank you for help, I now see that my post was way too long and boring. have a nice day, ~a friend. – NRagot Aug 10 '16 at 17:58
  • You're welcome. Your English is fine; I just found ways to deliver your knowledge with a little more impact. Good ideas deserve good delivery. – Prune Aug 10 '16 at 23:52