Java сделать окно поверх всех окон

Обновлено: 03.05.2024

Я читал об использовании JDialog для обертывания JFXPanel, чтобы использовать метод alwaysOnTop JDialog. Это работает, но у меня небольшая проблема с этим хаком.

Поскольку я использую эту технику для создания дополнительных окон для моего основного приложения (всплывающих окон и т. Д.), Мне нужно установить их поверх главного окна. Если я использую для этого хак-оболочку, верхняя панель «всегда поверх» всего (включая другие приложения).

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

Я предлагаю не использовать JDialog и JFXPanel , а использовать только этапы JavaFX .

Сделайте свой вторичный экран a Stage и вызовите secondaryStage.initOwner (primaryStage), прежде чем показывать вторичный этап.

Из документации Stage:

A stage can optionally have an owner Window. When a window is a stage's owner, it is said to be the parent of that stage . . . A stage will always be on top of its parent window.

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

Обновление: ответы на дополнительные вопросы из комментариев

I don't want there to be any interaction with the main stage once the secondary is open (the secondary window must be closed to allow interaction again).

Чтобы заблокировать ввод в первичный этап, перед показом вторичного этапа вызовите: secondaryStage.initModality (Modality.WINDOW_MODAL) .

Вы можете использовать APPLICATION_MODAL вместо WINDOW_MODAL, если вы предпочитаете блокировать весь ввод в любое другое окно вашего приложения - какое из них использовать, зависит от желаемого пользовательского опыта.

There's nothing obvious in the api that would center the secondary screen on the main screen. It just always centers on the monitor, no matter where the main screen is.

Эта часть вопроса является дубликатом Центрального расположения сцены . Ответ на дубликат содержит образец кода для выполнения центрирования дочернего окна.

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

Есть образец проекта, который я создал для относительного позиционирования дочерних диалоговых окон, что может быть полезно.

Просто для центрирования внутри родителя вам, вероятно, лучше всего запросить местоположение и ширину сцены перед отображением дочернего элемента, а затем соответствующим образом установить координаты x и y дочернего элемента при его отображении. Все это можно сделать на основе свойств окон x , y и ширины .

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

Со временем все функции, которые вы запрашиваете, вероятно, перейдут в базовую платформу JavaFX, но я не думаю, что для JavaFX 2.2 это все еще достаточно.

Добрый вечер! Есть проблема. Имеется 2-а jFrame. Необходимо расположить jFrame таким образом, чтобы при запуске он был всегда поверх другого jFrame. Работаю на старой Java - а точнее 1.4.2. Вариант setAlwaysOnTop(true) - не работает, по очевидным причинам.

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

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

1 ответ 1

поменяйте базовый класс для "2-а jFrame" на JDialog вместо JFrame, и сделайте диалог модальным.

а я попробовал так:

Я преобразовал класс JTextFieldDemo так как ты сказал. Пока результат остался таким же. Вот что я добавил и преобразовал: public class JTextFieldDemo extends JDialog setModal(true);

для чего вам нужно первое окно которое отображается? только для того чтоб ввести имя пользователя? если так тогда вам вообще не надо ничего придумывать с 2мя окнами. сначала в коде вызываете: JOptionPane.showInputDialog ( message ) а потом уже после него ваше основное окно игры. и передаете ему данные из диалога.

из первого окна необходимо будет передавать данные в xml файл по нажатию на кнопку "ок" которую я еще просто не добавил на поле. А после передачи, при наджатии на элементе меню "statistic" должно появиться окно с результатами - то есть с именем игрока. Если есть предложения по упрощению идеи - я открыт для предложений

я думал вам просто надо ввести имя пользователя перед началом игры, в этом случае стоит использовать стандартный диалог. а кнопку для просмотра статистики лучше конечно же сделать на основной форме, после чего собственно будет считыватся xml файл. а запись статистики после окончания игры (или при закрытии окна). проще было бы если б вы описали "бизнес-задачу" а не конкретный "камень" о который вы споткнулись, в таком случае можна было бы предлагать более конкретно по теме

Я иду поэтапно. На данный момент меня интересует только один вопрос - как сделать так что бы при старте программы диалог был всегда сверху программы.

Я создал DialogUtil, который показывает номера JOptionPan в разных ситуациях. иногда в моем классе действий вызывается этот метод с нулевыми параметрами, как показано ниже.

В этом случае JOptionPane не отображается в верхней части окна.

Как я могу добавить что-то в JOptionPane, чтобы оно всегда отображалось вверху?

Есть две возможные проблемы

JOptionPane вызывается из EDT, тогда на экране видна только панель инструментов (на экране видна подпись, полученная из Native OS, RootPane не видна)

там вы можете протестировать функции JOptionPanes, где JOptionPane.showInternalMessageDialog () создает проблемы во всех случаях, когда есть другой JDialog с setModal (true), настоящая причина, по которой я не знаю, то же самое должно быть с ModalityTypes

невозможно одновременно отображать на экране две панели JOptionPanes

Если ваш класс имеет расширенный JFrame, просто установите свойство класса setAlwaysOnTop (true); в любом месте в конструкторах перед JOptionPane.showMessageDialog (null, "OKay");

Я использую его для копирования файла и проверки, даже не нужен JFrame, а JOptionPane.

P.S. Если вы не хотите, чтобы основной JFrame всегда отображался вверху, вам нужно создать фиктивный JFrame или сбросить свойство setAlwaysOnTop (false); после JOptionPane.

Попробуйте указать корневую панель в качестве 1-го значения в разделе showMessageDialog

Я не знаю, что такое WebOptionPane или WebPanel , но если они основаны на JOptionPane , проблема в том, что вы передаете null для этого первого аргумента к методу showXXX() . Если вы хотите, чтобы JOptionPane был модальным - что заставляет его быть перед указанным окном - тогда вам нужно указать окно (то есть JFrame - для этого первого аргумента.

Вы можете установить JOptionPane всегда сверху, используя этот код: -

Вы пробовали что-то подобное?

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

Если у вас есть существующее окно или диалоговое окно, и вы хотите вывести его наверх, но не хотите постоянно устанавливать alwaysOnTop, это должно сработать, оставив только старое значение alwaysOnTop:

Я кое-что читал и обнаружил, что Java Swing не может оставаться поверх полноэкранных приложений без ужасного эффекта мерцания. Это правда? Эффект мерцания: у меня есть поток, который обновляет frame.setAlwaysOnTop () до true каждые 200 мс.

Прежде чем приступить к переписыванию своего приложения, обратите внимание на это эссе: Как создать самое верхнее окно, которое никогда не закрывается другими самыми верхними окнами?

Полноэкранное приложение какое-то время будет иметь приоритет, а затем станет самым верхним элементом. Когда это произойдет, поток обновится, и моя программа будет всегда вовремя. Что я не делал, что делал frame.repaint (), когда я делал то, что все работало нормально. Спасибо всем извините за плохую пометку

1 ответ

Краткий ответ: не совсем, нет.

В этой ситуации дисплей раскрашивается, когда этого требует приложение (что практически всегда либо «максимально быстро», либо «синхронизируется со следующим сканированием монитора»), НЕ когда графический интерфейс Windows считает, что это подходящее время. Итак, все, что нарисовано, когда Windows считает, что это хорошая идея, будет мерцать; Windows закрашивает ваше «всегда сверху» окно поверх «окна» приложения в Z-порядке графического интерфейса, затем приложение закрашивает окно, рисуя прямо на его прямоугольник. Это заставляет Windows аннулировать и перерисовывать ваше окно, и цикл продолжается.

Решение состоит не только в том, чтобы сделать окно «всегда наверху», но и каким-то образом программно «переключать задачи» с окна полноэкранного приложения на ваше. Для этого может потребоваться, чтобы у вашего приложения были привилегии, которые большинство управляемых сред выполнения не могут или не могут предоставить. Если это возможно, тогда, когда это произойдет, полноэкранное приложение будет минимизировано (что может быть или не быть ОГРОМНОЙ проблемой для ваших пользователей; что бы ваше приложение ни пыталось мне сказать, почти наверняка НЕ ​​стоит сворачивать мой сеанс StarCraft 2. посреди сетевой рукопашной).

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

Кейт, ты просто бросаешь на меня бомбы знания. Я заметил, что если я начинаю бороться за верхнее окно с приложением, например, с игрой, частота кадров в игре резко снижается. Это связано с тем, что цикл прерывается или мое приложение не дает игре то, что она хочет (чтобы она была на вершине)? Ps, когда вы говорите, вероятно, нет, это дает мне некоторую надежду, что я смогу найти какое-то решение. Я продолжу поиски и посмотрю, что делают некоторые хаки, чтобы оставаться на вершине / манипулировать программой, к которой они прикреплены.

В 2013-году Facebook выпустил функцию Chat Heads для своего мессенджера, который позволяет вести переписку, не открывая сам мессенджер путем нажатия на маленькое круглое окошко, которое всегда висит на дисплее даже поверх других приложений:

image

Facebook одним из первых продемонстрировал реализацию «Drawing over other apps». Данную возможность разработчики сейчас используют в различных типах приложений — от боковых смарт-меню до записи экрана. В этой статье, хочу продеменстрировать процесс написания приложения-поверх-других-приложений на примере «анти-шпионской» программы Khameleon.

Для начала обозначу цели приложения, который будет реализован как пример приложения-поверх-других-приложений. Допустим нужно, чтобы рядом стоящие люди не могли с легкостью видеть контент моего смарфтона, пока я им пользуюсь. То есть необходима возможность:

  1. Скрывать часть дисплея, чтобы видеть только необходимую область
  2. Вместо скрытой области, показывать любой желаемый контент (например заданную веб страницу)

С функционалом приложения определились — теперь приступим к самому туториалу. Для написания приложения-поверх-других-приложений есть две самых главных составляющих:

  • Service, через который ведется основной контроль и логика приложения
  • Layout, который собственно и является GUI


А для API > 23, т.е. Android M, нужно запросить разрешение в главном Activity:

После того как разрешение получено, укажем Layout, который нужно отобразвить на экране (многие элементы убраны для демонстрации):


В корневой RelativeLayout (по вашему усмотрению) можно поместить любые View'шки как обычно. View с нам нужен для того, чтобы показать как динамично менять размеры Layout. То есть через эту View'шку можно будет расстягивать и сжимать корневой RelativeLayout.

Как только у нас есть минимальный Layout, необходимо реализовать самый обычный Service. Единственная особенность сервиса в добавлении ранее созданного Layout:


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


Если потянуть за край Layout вверх или вниз, его высота соответственно сжимается и расширяется.

Мы рассмотрели минимальные необходимые шаги для написания приложения-поверх-других-приложений. Полный код для приложенения Khameleon, продемонстрированный выше, можно найти здесь.

Читайте также: