Можно ли вывести JFrame вперед, но НЕ фокусировать? - PullRequest
14 голосов
/ 25 января 2011

Я пишу Java-приложение (Swing GUI), которое периодически выдает JFrame.

Возможно ли как-то вывести окно на передний план (foo.setAlwaysOnTop (true) было бы еще лучше), но без с фокусировкой?

Некоторые люди время от времени отводят глаза от экрана, чтобы посмотреть на клавиатуру во время набора текста, и я уверен, что если это окно всегда будет захватыватьлюди, которые фокусируются на клавиатуре, очень раздражаются, потому что они теряют довольно много нажатий клавиш каждый раз, когда они появляются незаметно.

В других случаях, даже когда пользователь действительно способен печатать, не глядя на клавиатуру всевремя, когда всплывающее окно и фокусировка могут вызвать нежелательные действия из самого всплывающего окна (например, некоторая комбинация Tab + Enter, когда пользователь случайно выбирает вариант, который он действительно не выбрал бы в противном случае)).

Заранее спасибо!

Обновление

Как предполагает Джонас, foo.setFocusableWindowState(false); кажетсяработать, если вызывается после отображения окна (проверено только на Gnome).

Это не работает:

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

Однако это делает :

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

Мне нужно посмотреть, есть ли событие, которое я могу поймать / прослушать, которое позволяет мне делать foo.setFocusableWindowStatue(true);, когда это уместно.

Я считаю, что моя проблема решена.

Ответы [ 6 ]

14 голосов
/ 25 января 2011

Это может работать:

foo.setFocusableWindowState(false);
3 голосов
/ 22 июня 2014

Начиная с Java 1.7 вы можете звонить

frame.setAutoRequestFocus(false);
2 голосов
/ 08 ноября 2011

Я недавно столкнулся с той же проблемой, и предварительное решение было:

JFrame frame = ...;
frame.setExtendedState(JFrame.NORMAL);
frame.setAlwaysOnTop(true);
frame.requestFocus();
frame.setAlwaysOnTop(false);
0 голосов
/ 03 января 2019

JInternalFrame toFront() звонки на moveToFront()

Переопределить 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();
        }
    }

исправление находится в moveToFront, чтобы проверить, есть ли у ребенка фокус, и если это так, временно запросите фокус на внутреннем фрейме. После того, как внутренняя рамка переместилась вперед, запросите фокусировку назад на ранее сфокусированном компоненте. Это обеспечит генерацию соответствующих событий.

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

0 голосов
/ 02 ноября 2017

Если вы хотите вызвать setFocusableWindowState (true) в событии (то есть не ждать, например, 1 секунду), вы можете добавить WindowListener (например, полученный из WindowAdapter), который изменяет свойство:

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

    appFrame.setFocusableWindowState(false);
    appFrame.setVisible(true);
0 голосов
/ 25 января 2011

Предложение: В компонент GUI, который создает фрейм, поместите 2 последовательных вызова:

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

1-й выводит окно нового JFrame наверх, 2-й сохраняет окно, где пользователь печатает сверху.

...