JWindow всегда на высоте

Я использовал Java и Swing.

У меня два окна MainWindow и PointWindow.

MainWindow - это окно JFrame.

PointWindow расширяет JWindow.

Я хочу, чтобы PointWindow всегда было сверху (никогда не под другими окнами или компонентами). Я установил в конструкторе PointWindow setAlwaysOnTop(true), но проблема в том, что когда я нажимаю на MainWindow (фокус), затем другим способом, например, щелкаю на моем рабочем столе (пустое место) и пытаюсь перетащить PointWindow, тогда он находится под моим MainWindow.

Есть ли способ сохранить PointWindow всегда поверх всех компонентов?

ИЗМЕНИТЬ

В конструкторе я попытался использовать WindowListener, как показано ниже.

this.addWindowListener(new WindowAdapter() {
    @Override
    public void windowDeactivated(WindowEvent e) {
        toFront();
    }

    @Override
    public void windowLostFocus(WindowEvent e) {
        toFront();
    }
});

... но это не работает, события не перехватываются


person ACz    schedule 22.12.2016    source источник
comment
setAlwaysOnTop (истина); должен сделать это   -  person Jarlik Stepsto    schedule 22.12.2016
comment
Но не. Проблема проявляется, когда я потерял фокус на PointWindow, щелкнул в другом месте (не в проекте) и попытался перетащить.   -  person ACz    schedule 22.12.2016
comment
вы можете прослушивать другие события (слушатель состояния окна) или создать верхний поток для вызова .toFront();   -  person Jarlik Stepsto    schedule 22.12.2016
comment
@pzaenger это должно быть JWindow   -  person ACz    schedule 22.12.2016
comment
@JarlikStepsto Я пытаюсь добавить в конструктор WindowListener с переопределенными методами как windowDeactivated или windowLostFocus, но он не перехватывается.   -  person ACz    schedule 22.12.2016
comment
неукрашенный JDialog более удобен, чем JWindow,   -  person mKorbel    schedule 22.12.2016
comment
Не могли бы вы опубликовать минимальный пример? Стандартное поведение заключается в том, что JWindow с alwaysOnTop(true) действительно остается поверх JFrame. Поэтому я предполагаю, что что-то конкретное для вашего кода меняет это поведение.   -  person Markus Fischer    schedule 22.12.2016
comment
@mKorbel Я пытаюсь найти решение для JWindow, потому что я установил фон и многие вещи, которые я не могу сделать с JDialog. Попробуйте ответить на мой вопрос.   -  person ACz    schedule 22.12.2016
comment
JWindow не получает/обрабатывает события фокуса.   -  person Markus Fischer    schedule 22.12.2016
comment
Обычный JWindow нельзя перетаскивать. Когда вы говорите о перетаскивании JWindow, вы вызываете пользовательский код, который может изменить z-порядок компонентов на экране. Не могли бы вы показать обработку операций перетаскивания?   -  person Markus Fischer    schedule 22.12.2016
comment
@MarkusFischer Я добавляю MouseAdapter как MouseListener в конструктор.   -  person ACz    schedule 22.12.2016
comment
@Markus Fischer JWindow с родителем (JFrame) обрабатывает все события, согласен с некоторыми проблемами, например. JTextComponents не редактируется в JWindow без родителя   -  person mKorbel    schedule 22.12.2016


Ответы (2)


Если оба окна принадлежат одному и тому же приложению,

setAlwaysOnTop(true);

метод должен делать то, что вы хотите.

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

В следующем примере fr — это ваше окно

Thread th = new Thread(){
        public void run(){
            boolean live = true;
            while(live){
                try{
                    fr.toFront();
                    fr.setAlwaysOnTop(true);
                }catch(Exception e1){
                    e1.printStackTrace();
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        }
}

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

ИЗМЕНИТЬ:

если вы просто хотите, чтобы окно было перед другим окном (событие после восстановления фокуса), вы можете добавить и

FocusListener к вашему JFrame и вызовите toFront в вашем окне, когда срабатывает событие focusGained(FocusEvent e).

Или вы можете создать JWindow с фреймом в качестве родителя: new JWindow(jframeParent); таким образом, ваш JWindow получит все события.

Или просто использовать недекорированный JFrame вместо JWindow

EDIT2:

Если вы просто хотите, чтобы окно было сверху, при нажатии на него появится MouseListener — правильный способ сделать это.

person Jarlik Stepsto    schedule 22.12.2016
comment
Хм, может быть, я могу определить, когда мой JWindow восстановит фокус, а затем запустить поток? - person ACz; 22.12.2016
comment
см. редактирование. Вы можете обнаружить, когда ваш jframe получает фокус, затем нажмите окно поверх него и снова установите allwaysOnTop - person Jarlik Stepsto; 22.12.2016
comment
FocusListener не обнаруживает. Я нашел решение, как я написал. Спасибо за Ваш ответ :) - person ACz; 22.12.2016
comment
фокус lsitener работает только с JFrame, а не с JWindow. Но вы можете нажать на окно, когда ваш кадр получит фокус :). Другим способом может быть недекорированный JFrame, который похож на JWindow, но с возможностью фокусировки. Но я добавил ваше решение в ответ, чтобы у других людей был полный обзор :) - person Jarlik Stepsto; 22.12.2016

РЕШЕНИЕ

Я добавляю MouseAdapterкак MouseListener к PointWindow, и когда обнаруживается событие mousePressed, то делаю toFront() и работает нормально, но есть один побочный эффект, это означает, что есть момент, когда окно скрывает и показывает (очень быстро).

person ACz    schedule 22.12.2016