Ответ 1
Возможное решение:
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
myFrame.toFront();
myFrame.repaint();
}
});
У нас есть Java-приложение, которое нужно вывести на передний план, когда механизм телеуправления активирует что-то в приложении.
Чтобы получить это, мы реализовали в вызываемом методе класса, который представляет собой Рам нашего приложения (расширение JFrame) после реализации:
setVisible(true);
toFront();
В Windows XP это срабатывает при первом вызове, во второй раз мигает только вкладка на панели задач, рамка больше не выходит на передний план. То же самое касается Win2k. На Vista это работает нормально.
Любые идеи?
Возможное решение:
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
myFrame.toFront();
myFrame.repaint();
}
});
У меня была та же проблема с приведением 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 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.
В Windows есть средство, предотвращающее кражу фокуса; вместо этого он мигает значок панели задач. В XP он включен по умолчанию (единственное место, которое я видел для его изменения, - это использование TweakUI, но где-то есть параметр реестра). В Vista они, возможно, изменили значение по умолчанию и/или выставили его как пользовательскую настройку с помощью готового пользовательского интерфейса.
Предотвращение форсирования Windows на передний план и фокус - это функция с 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, этот код работает нормально.
Здесь используется метод, который ДЕЙСТВИТЕЛЬНО работает (протестирован в Windows Vista): D
frame.setExtendedState(JFrame.ICONIFIED);
frame.setExtendedState(fullscreen ? JFrame.MAXIMIZED_BOTH : JFrame.NORMAL);
Полноэкранная переменная указывает, хотите ли вы, чтобы приложение запускалось полноэкранным или оконным.
Это не мигает панель задач, но надежно переводит окно вперед.
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: -)
Этот простой метод отлично работал у меня в Windows 7:
private void BringToFront() {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if(jFrame != null) {
jFrame.toFront();
jFrame.repaint();
}
}
});
}
Я тестировал ваши ответы, и только Stefan Reich one работал на меня. Хотя мне не удалось восстановить окно до его предыдущего состояния (максимально/нормальное). Я нашел эту мутацию лучше:
view.setState(java.awt.Frame.ICONIFIED);
view.setState(java.awt.Frame.NORMAL);
Это setState
вместо setExtendedState
.
Самый простой способ, который я обнаружил, не имеет несогласованности между платформами:
SetVisible (ложь); SetVisible (истина);
Правила, определяющие, что происходит, когда вы .toFront() JFrame одинаковы в окнах и в 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);
}
});
В javadoc для метода toFront() существует множество оговорок, которые могут вызывать проблемы.
Но я все равно пойму, когда "только мигает вкладка на панели задач", было ли минимизировано приложение? Если это так, может применяться следующая строка из javadoc:
"Если это окно виден, оно выводит это окно на передний план и может превратить его в фокусное окно".
Чтобы избежать потери фокуса окна, когда его возвращение в видимое после того, как оно было скрыто, все, что вам нужно:
setExtendedState(JFrame.NORMAL);
Так же:
defaultItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showWindow();
setExtendedState(JFrame.NORMAL);
}
});