0

We had a request that some dialogs should always be on top based on some control. This must be switched on/off on a per dialog basis. Using the following code, and going through the following steps seems to me like a Java bug:

  1. Set dialog1 on top. Check it stays on top.
  2. Set dialog2 on top. Check both dialogs stay on top.
  3. Set dialog1 not on top.

Expected: dialog2 remains on top and dialog1 doesn't

Actual: none of the dialogs remain on top.

This has some connection with the owner of the dialogs. If you uncomment the block comments, everything works as expected but I don't think this is normal behaviour since Always on Top should not be connected to the parent. Is this normal or is it an issue with Swing? Unfortunately setting a new owner for each dialog introduces other issues.

public static void main(String[] args) {
    final JFrame rahan = new JFrame("Rahan");
    rahan.setSize(new Dimension(1000,1000));
    rahan.setVisible(true);


    JDialog d1 = getJDialog(/*new JFrame()*/);
    JDialog d2 = getJDialog(/*new JFrame()*/);
}

private static JDialog getJDialog(/*JFrame owner*/) {
    final JDialog jDialog = new JDialog(/*owner*/);
    final JButton onTop = new JButton("OnTop");
    onTop.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            jDialog.setAlwaysOnTop(!jDialog.isAlwaysOnTop());
        }
    });
    jDialog.add(onTop);
    jDialog.setVisible(true);
    jDialog.pack();
    return jDialog;
}
Vlad Topala
  • 896
  • 1
  • 8
  • 34

3 Answers3

1

If I run your application like this :

public static void main(String[] args) {
    final JFrame rahan = new JFrame("Rahan");
    rahan.setSize(new Dimension(1000,1000));
    rahan.setVisible(true);


    JDialog d1 = getJDialog(rahan);
    JDialog d2 = getJDialog(rahan);
}

    private static JDialog getJDialog(JFrame owner) {
        final JDialog jDialog = new JDialog(owner);
        final JButton onTop = new JButton("OnTop");
        onTop.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent e) {
                 jDialog.setAlwaysOnTop(!jDialog.isAlwaysOnTop());       
            }
        });
        jDialog.add(onTop);
        jDialog.setVisible(true);
        jDialog.pack();
        return jDialog;
    }

    }

It works perfectly. The two dialogs are always on top, and it is not modal so you can click into the frame.

You can try setting the dialog to be modal like this :

jDialog.setModal(true);

But this is kind of going against what you are achieving right?

Oliver Watkins
  • 12,575
  • 33
  • 119
  • 225
  • Modal dialogs being hidden by AlwaysOnTopDialogs is another issue I encountered but unfortunately in your example the 2 dialogs are always on top of the frame. The button doesn't work anymore for toggling the "AlwaysOnTop" status in relation to the frame. Also, my issue is still not solved. Try using the browser as comparison and do the 3 steps I presented. Issue is still present if the dialogs have the same parent. – Vlad Topala Dec 24 '15 at 12:58
  • I think you mean : If you press the button then the dialog should go to the top? – Oliver Watkins Dec 24 '15 at 13:02
  • I mean they should work independently. If both are to the front and you disable one of them, both will go under the browser instead of just the disabled one. – Vlad Topala Dec 24 '15 at 13:03
  • so... you mean if I press the buttojn it will go BEHIND the frame? That is what you want to achieve? – Oliver Watkins Dec 24 '15 at 13:03
  • I am still not quite sure what you want to achieve. If you want to control the order of the controls then you have to play with Z-Order : http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/Container.html#setComponentZOrder%28java.awt.Component,%20int%29 – Oliver Watkins Dec 24 '15 at 13:05
1

Looking at the code for setAlwaysOnTop, these are dispatched directly to the window peer, so this might be an OS-dependent problem.

Secondly have you tried doing all the creation on the event dispatch thread? That was suggested in a previous post on this issue.

JDialog.setAlwaysOnTop(true) brings all dialogs to the front under Windows

Community
  • 1
  • 1
Sanjay Manohar
  • 6,920
  • 3
  • 35
  • 58
  • Same behavior even if everything is done on EDT. Again, my problem is that they don't act independently when having the same owner. If both dialogs are alwaysOnTop and I set one of them not to be AlwaysOnTop anymore, they'll both stop being always on top. I don't think this is normal behavior since the owner should not influence this. – Vlad Topala Dec 28 '15 at 07:22
1

Not sure if this question is still relevant, but I found a potential workaround to the problem. If you keep a list of all the potentially 'Always on Top' windows that you add to every time a new one is created, you can go back and toggle them off then on again to put them back on top as they should be.

ArrayList<Window> = new ArrayList<Window>();
.
.
.
void createWindow() {
    Window w = new Window();
    windowList.add(w);
}

Then when one of the window's 'Always on Top' button is turned off, you go back to your windowList and toggle all the ones that are set to always on top. The following should be in your actionPerformed function in the action listener for toggling 'Always on Top':

if (!windowAlwaysOnTopButton.isSelected()) {
    ArrayList<Window> turnedOff = new ArrayList<Window>();
    for (Window w : windowList) {
        if (w.isAlwaysOnTop()) {
            w.setAlwaysOnTop(false);
            turnedOff.add(w);
        } 
    } 
    for (Window w : turnedOff) {
        w.setAlwaysOnTop(true);
    } 
}

You need the two for loops and the turnedOff list because if you toggle each one off then on again in the same loop, you run into the original problem where if Windows A and B are always on top then Window A is turned off, Window B will also be turned off. That is why you need to turn them all off, and then loop thru again to turn them back on. I realize this may be a hackey solution, but if it worked for me it might just work for you. Cheers!

Austin Adams
  • 231
  • 1
  • 10
  • Well, not relevant anymore as we already have a solution in place based on (if I remember correctly) having a new owner for each dialog, but I agree your solution works even if it looks hackey. Although still not sure why it works the way it does. – Vlad Topala Oct 05 '17 at 00:44