문제

I'm writing a Java app (Swing GUI) that periodically pops up a JFrame.

Is it possible somehow to bring the window to front (foo.setAlwaysOnTop(true) would be even better) but without having it focus?

Some people move their eyes away from the screen from time to time to look at their keyboard while typing, and I'm sure that if this window would always capture the keyboard focus people would get really annoyed as it's causing them to lose quite a few keystrokes every time it pops up unnoticed.

In other cases, even when the user is actually capable of typing without looking at the keyboard all the time, having a window pop up and get focus could cause unwanted actions from the pop-up window itself (some Tab+Enter combination for example, where the user accidentally selects an option she really wouldn't had selected otherwise).

Thanks in advance!

Update

As Jonas suggests, foo.setFocusableWindowState(false); seems to work if called after the window has been rendered (tested on Gnome only).

This does not work:

foo.setFocusableWindowState(false);
foo.setVisible(true);
foo.setFocusableWindowState(true);

However, this does:

foo.setFocusableWindowState(false);
foo.setVisible(true);
Thread.sleep(1000);
foo.setFocusableWindowState(true);

I'll have to see if there's an event I can catch/listen to that allows me to do foo.setFocusableWindowStatue(true); when appropriate.

I consider my problem solved.

도움이 되었습니까?

해결책

This may work:

foo.setFocusableWindowState(false);

다른 팁

As of Java 1.7 you can call

frame.setAutoRequestFocus(false);

I recently ran into the same problem, and the tentative solution has been:

JFrame frame = ...;
frame.setExtendedState(JFrame.NORMAL);
frame.setAlwaysOnTop(true);
frame.requestFocus();
frame.setAlwaysOnTop(false);

Suggestion: In the GUI Component that creates the Frame, put 2 consecutive calls:

frameJustCreated.requestFocus();
this.requestFocus();

1st one bring the window of the new JFrame to the top, 2nd one keeps the window where the user is typing at the top.

If you want to call setFocusableWindowState(true) in an event (so, not to wait e.g. 1 second), you can add a WindowListener (e.g. derived from WindowAdapter) that changes the property:

    appFrame.addWindowListener(new WindowAdapter() {
        @Override
        public void windowOpened(WindowEvent e) {
            super.windowOpened(e);
            e.getWindow().setFocusableWindowState(true);
        }
    });

    appFrame.setFocusableWindowState(false);
    appFrame.setVisible(true);

JInternalFrame toFront() calls to moveToFront()

Override moveToFront()

public void moveToFront() {
        Window window = SwingUtilities.getWindowAncestor(this);
        Component focusOwner = (window != null) ? window.getFocusOwner() :
                                null;
        boolean descendant = false;

        if (window != null && focusOwner != null &&
                      SwingUtilities.isDescendingFrom(focusOwner, this)) {
            descendant = true;
            requestFocus();
        }

        super.moveToFront();

        if (descendant) {
            focusOwner.requestFocus();
        }
    }

the fix is in moveToFront to check if a child has focus, if it does, then temporarily request focus on the internal frame. After the internal frame has movthe ed to front, then request focus back on the previously focused component. This will ensure the appropriate events are generated.

refer https://bugs.openjdk.java.net/browse/JDK-4309079

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top