У нас есть приложение Java, которое нужно вывести на передний план, когда механизм телеуправления активирует что-то в приложении.
Чтобы получить это, мы реализовали в вызываемом методе класса, который представляет собой фрейм нашего приложения (расширение JFrame), следующую реализацию:
setVisible(true);
toFront();
В Windows XP это работает при первом вызове, во второй раз мигает только вкладка на панели задач, рамка больше не выходит на передний план. То же самое и с Win2k. В Vista вроде нормально работает.
Есть ли у вас какие-либо идеи?
Правильный ответ - вызвать в toFront() по EDT, используя invokeLater. Ниже приведен простой ответ, но это не принятый ответ. Но это действительно работает. Прекрасно.
Я знаю, что это устарело, но такое бывает и в OSX.
У меня возникла эта проблема, но, похоже, ни один из приведенных ниже ответов не решает ее. Я уверен, что это вызвано тем, что окна не позволяют мне «украсть» фокус для моего первого окна в приложении.




В javadoc есть множество предостережения для метода toFront (), которые могут вызывать вашу проблему.
Но все равно погадаю, когда "мигает только вкладка в панели задач", приложение свернуто? В таком случае может применяться следующая строка из javadoc:
«Если это Окно видно, переносит это Окно на передний план и может сделать его окном в фокусе».
В Windows есть возможность предотвращать перехват фокуса окнами; вместо этого мигает значок на панели задач. В XP он включен по умолчанию (единственное место, где я видел, чтобы изменить его, - это TweakUI, но где-то есть параметр реестра). В Vista они могли изменить значение по умолчанию и / или выставить его как доступную пользователю настройку с помощью готового пользовательского интерфейса.
Предотвращение того, чтобы окна выдвигались вперед и фокусировались, - это функция, появившаяся со времен Windows 2K (и я, например, благодарен за это).
Тем не менее, у меня есть небольшое Java-приложение, которое я использую, чтобы напоминать мне о записи моих действий во время работы, и оно делает себя активным окном каждые 30 минут (конечно, настраиваемым). Он всегда стабильно работает под Windows XP и никогда не мигает в окне заголовка. Он использует следующий код, вызываемый в потоке пользовательского интерфейса в результате срабатывания события таймера:
if (getState()!=Frame.NORMAL) { setState(Frame.NORMAL); }
toFront();
repaint();
(первая строка восстанавливается, если свернута ... на самом деле она восстановит ее, если она развернута, но у меня этого никогда не было).
Хотя обычно это приложение свернуто, довольно часто оно просто находится за моим текстовым редактором. И, как я уже сказал, это всегда работает.
У меня есть представление о том, в чем может быть ваша проблема - возможно, у вас есть состояние гонки с вызовом setVisible (). toFront () может быть недействительным, если окно фактически не отображается при его вызове; У меня раньше была эта проблема с requestFocus (). Возможно, вам потребуется поместить вызов toFront () в прослушиватель пользовательского интерфейса для события, активируемого окном.
2014-09-07: В какой-то момент вышеуказанный код перестал работать, возможно, на Java 6 или 7. После некоторых исследований и экспериментов мне пришлось обновить код, чтобы переопределить метод toFront окна, сделайте это (вместе с измененным кодом из того, что указано выше):
setVisible(true);
toFront();
requestFocus();
repaint();
...
public @Override void toFront() {
int sta = super.getExtendedState() & ~JFrame.ICONIFIED & JFrame.NORMAL;
super.setExtendedState(sta);
super.setAlwaysOnTop(true);
super.toFront();
super.requestFocus();
super.setAlwaysOnTop(false);
}
Что касается Java 8_20, этот код, похоже, работает нормально.
+1 за поддержку, не позволяющую окнам красть фокус. Ненавижу, когда такое случается, когда я печатаю документ.
Я полностью согласен с вами против кражи фокуса, но именно в этом случае пользователь ожидает, что приложение выйдет на первый план. Но было бы нехорошо изменить настройки реестра и полностью изменить поведение Windows.
Я предполагаю, что super.setAlwaysOnTop(false); так устроен, что окно не всегда наверху, что необходимо, чтобы избавиться от true, который мы установили ранее, чтобы вывести окно на передний план, верно? Я спрашиваю, потому что с вашим кодом в моем случае окно все еще всегда наверху, чего я, очевидно, не хочу. Запуск jre1.8.0_66 в Windows 10.
@ Брэм: Да, это правильно. Я запускаю код в одной и той же версии Java и Windows, и он не всегда оказывается поверх других окон. Возможно, нет необходимости устанавливать всегда сверху, но я думаю, что в противном случае Windows просто мигает строкой заголовка, по крайней мере, при некоторых условиях.
Хм, странно. Не могли бы вы взглянуть на аналогичный вопрос, в котором я ссылаюсь на этот ответ? Возможно, этот код более ясно показывает проблему: stackoverflow.com/questions/34637597/…
@ Брэм: Аааа. Я имеют видел, как это произошло. Я предполагаю, что если текущее окно получает пользовательский ввод между моментом вызова toFront и фактическим отображением, оно будет делать то, что вы описываете; фокус ввода остается в окне за ним. У меня такое случается, когда я кодирую. Временами это раздражает, потому что новое окно выглядит как будто имеет фокус. У меня даже была ситуация, когда ввод ключа отправляется в окна и то и другое. То, что я видел, похоже на ошибку в Windows, поскольку это только начало происходить в Win 10 и, похоже, попытка остановить кражу фокуса, пошла не так.
Возможное решение:
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
myFrame.toFront();
myFrame.repaint();
}
});
Возможно, стоит сначала запустить ВСЕ код пользовательского интерфейса внутри invokeLater? ;)
У меня не работало в Java 7 на KDE 4.9.5, окно все равно скрывалось под другими программами. Мне помогло изменение порядка вывода окон на фасад. Вместо того, чтобы скрывать одно окно и отображать второе окно, покажите второе окно, а затем скройте первое окно (JFrame).
Работает с Windows 10 под управлением Java 1.8 в апплете
Каким был бы обратный метод?
У меня была такая же проблема с выводом JFrame на передний план под Ubuntu (Java 1.6.0_10). И единственный способ решить эту проблему - предоставить WindowListener. В частности, мне пришлось настроить свой JFrame так, чтобы он всегда оставался наверху при вызове toFront(), и предоставить обработчик событий windowDeactivated для setAlwaysOnTop(false).
Итак, вот код, который можно поместить в базовый JFrame, который используется для получения всех фреймов приложения.
@Override
public void setVisible(final boolean visible) {
// make sure that frame is marked as not disposed if it is asked to be visible
if (visible) {
setDisposed(false);
}
// let's handle visibility...
if (!visible || !isVisible()) { // have to check this condition simply because super.setVisible(true) invokes toFront if frame was already visible
super.setVisible(visible);
}
// ...and bring frame to the front.. in a strange and weird way
if (visible) {
toFront();
}
}
@Override
public void toFront() {
super.setVisible(true);
int state = super.getExtendedState();
state &= ~JFrame.ICONIFIED;
super.setExtendedState(state);
super.setAlwaysOnTop(true);
super.toFront();
super.requestFocus();
super.setAlwaysOnTop(false);
}
Всякий раз, когда ваша рамка должна быть отображена или вынесена на первый план, звоните frame.setVisible(true).
Поскольку я перешел на Ubuntu 9.04, похоже, нет необходимости в наличии WindowListener для вызова super.setAlwaysOnTop(false) - как можно заметить; этот код был перенесен в методы toFront() и setVisible().
Обратите внимание, что метод setVisible() всегда следует вызывать в EDT.
Спасибо! Также связан этот вопрос: stackoverflow.com/questions/2315560/…
Он не компилируется мной из-за метода setDisposed (). Ничего не найдено.
@ ka3ak Это защищенный установщик, который может быть введен в предлагаемый базовый класс JFrame, чтобы отслеживать ситуацию с удаляемым фреймом. Метод dispose () необходимо переопределить вызовом setDisposed (true). Строго говоря, это необходимо не всем.
.setAlwaysOnTop(true); был единственным, который работал у меня при использовании JWindow.
setAlwaysOnTop(true) - единственный способ запустить его под Windows 10 - спасибо!
Самый простой способ, который я нашел, не имеет противоречий между платформами:
setVisible (ложь); setVisible (правда);
вызывает некоторое мигание, не так ли? красиво и просто :)
не работал для моего фонового процесса. Также окно становится белым для первого обновления, если вызывается из процесса переднего плана. Нельзя использовать для захвата экрана.
моргания можно избежать, проверив, отображается ли окно в виде значков или нет
Этот простой метод отлично работал у меня в Windows 7:
private void BringToFront() {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if (jFrame != null) {
jFrame.toFront();
jFrame.repaint();
}
}
});
}
repaint() не нужен, это сделал invokeLater(). Спасибо.
Правила, управляющие тем, что происходит, когда вы .toFront () JFrame, одинаковы в Windows и Linux:
-> если окно существующего приложения в настоящее время является окном в фокусе, то фокус переключается на запрошенное окно -> если нет, окно просто мигает на панели задач
НО :
-> новые окна автоматически получают фокус
Так что давайте воспользуемся этим! Хотите вывести окно вперед, как это сделать? Что ж :
Или в Java-коде:
// unminimize if necessary
this.setExtendedState(this.getExtendedState() & ~JFrame.ICONIFIED);
// don't blame me, blame my upbringing
// or better yet, blame java !
final JFrame newFrame = new JFrame();
newFrame.add(new JLabel("boembabies, is this in front ?"));
newFrame.pack();
newFrame.setVisible(true);
newFrame.toFront();
this.toFront();
this.requestFocus();
// I'm not 100% positive invokeLater is necessary, but it seems to be on
// WinXP. I'd be lying if I said I understand why
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
newFrame.setVisible(false);
}
});
На Win7 не заработало, мигают оба окна (если не скрою 2-е).
Творческий. Не работал для моего фонового процесса на Win7, когда он был покрыт. Новая рамка не подходит. Более старый JDK 6u21.
Hj, все ваши методы у меня не работают в Fedora KDE 14. У меня есть грязный способ вывести окно на передний план, пока мы ждем, пока Oracle исправит эту проблему.
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.InputEvent;
public class FrameMain extends javax.swing.JFrame {
//...
private final javax.swing.JFrame mainFrame = this;
private void toggleVisible() {
setVisible(!isVisible());
if (isVisible()) {
toFront();
requestFocus();
setAlwaysOnTop(true);
try {
//remember the last location of mouse
final Point oldMouseLocation = MouseInfo.getPointerInfo().getLocation();
//simulate a mouse click on title bar of window
Robot robot = new Robot();
robot.mouseMove(mainFrame.getX() + 100, mainFrame.getY() + 5);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
//move mouse to old location
robot.mouseMove((int) oldMouseLocation.getX(), (int) oldMouseLocation.getY());
} catch (Exception ex) {
//just ignore exception, or you can handle it as you want
} finally {
setAlwaysOnTop(false);
}
}
}
//...
}
И это отлично работает в моей Fedora KDE 14 :-)
Немного хакерский, у нас работает, но только при первом звонке :-). (Kubuntu 12.04) - другое решение не удалось
Это было единственное решение, которое сработало для меня (Windows Server 2012 R2) для проблемы, когда JFrame (вход в систему) открывается, но не имеет фокуса, пока пользователь не щелкнет по нему.
Вот метод, который ДЕЙСТВИТЕЛЬНО работает (проверено в Windows Vista): D
frame.setExtendedState(JFrame.ICONIFIED);
frame.setExtendedState(fullscreen ? JFrame.MAXIMIZED_BOTH : JFrame.NORMAL);
Переменная полноэкранного режима указывает, хотите ли вы, чтобы приложение работало в полноэкранном или оконном режиме.
При этом панель задач не мигает, но окно надежно выводится на передний план.
Спасибо за совет setExtendedState. Я использовал его вместе с решениями toFront () и repaint (), чтобы вывести окно на передний план, даже если оно было свернуто.
Подтверждено: это решение работает в WindowsXP, использование toFront приводит к миганию сообщения на панели задач. Спасибо!
Я проверил ваши ответы и у меня работал только Штефана Райха. Хотя мне не удалось восстановить окно в его предыдущее состояние (развернутое / нормальное). Я нашел эту мутацию лучше:
view.setState(java.awt.Frame.ICONIFIED);
view.setState(java.awt.Frame.NORMAL);
То есть setState вместо setExtendedState.
Чтобы окно не потеряло фокус при его возвращении в видимое состояние после того, как оно было скрыто, все, что необходимо:
setExtendedState(JFrame.NORMAL);
Вот так:
defaultItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showWindow();
setExtendedState(JFrame.NORMAL);
}
});
у вас есть образец такого поведения?