Как принести окно на фронт?

У нас есть Java-приложение, которое нужно вывести на передний план, когда механизм телеуправления активирует что-то в приложении.

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

setVisible(true);
toFront();

В Windows XP это срабатывает при первом вызове, во второй раз мигает только вкладка на панели задач, рамка больше не выходит на передний план. То же самое касается Win2k. На Vista это работает нормально.

Любые идеи?

Ответ 1

Возможное решение:

java.awt.EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        myFrame.toFront();
        myFrame.repaint();
    }
});

Ответ 2

У меня была та же проблема с приведением 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.

Ответ 3

В 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, этот код работает нормально.

Ответ 4

Здесь используется метод, который ДЕЙСТВИТЕЛЬНО работает (протестирован в Windows Vista): D

   frame.setExtendedState(JFrame.ICONIFIED);
   frame.setExtendedState(fullscreen ? JFrame.MAXIMIZED_BOTH : JFrame.NORMAL);

Полноэкранная переменная указывает, хотите ли вы, чтобы приложение запускалось полноэкранным или оконным.

Это не мигает панель задач, но надежно переводит окно вперед.

Ответ 5

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: -)

Ответ 6

Этот простой метод отлично работал у меня в Windows 7:

    private void BringToFront() {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                if(jFrame != null) {
                    jFrame.toFront();
                    jFrame.repaint();
                }
            }
        });
    }

Ответ 7

Я тестировал ваши ответы, и только Stefan Reich one работал на меня. Хотя мне не удалось восстановить окно до его предыдущего состояния (максимально/нормальное). Я нашел эту мутацию лучше:

view.setState(java.awt.Frame.ICONIFIED);
view.setState(java.awt.Frame.NORMAL);

Это setState вместо setExtendedState.

Ответ 8

Самый простой способ, который я обнаружил, не имеет несогласованности между платформами:

SetVisible (ложь); SetVisible (истина);

Ответ 9

Правила, определяющие, что происходит, когда вы .toFront() JFrame одинаковы в окнах и в linux:

- > если окно существующего приложения в настоящее время является сфокусированным окном, затем сфокусируйте свопы в запрошенном окне - > если нет, окно просто мигает на панели задач

НО:

- > новые окна автоматически получают фокус

Так что давайте использовать это! Вы хотите принести окно на фронт, как это сделать? Хорошо:

  • Создать пустое нецелевое окно
  • Показать
  • Подождите, пока он появится на экране (setVisible делает это)
  • Когда показано, запросите фокус для окна, которое вы действительно хотите перенести на
  • скрыть пустое окно, уничтожить его

Или в 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);
  }
});

Ответ 10

В javadoc для метода toFront() существует множество оговорок, которые могут вызывать проблемы.

Но я все равно пойму, когда "только мигает вкладка на панели задач", было ли минимизировано приложение? Если это так, может применяться следующая строка из javadoc:

"Если это окно виден, оно выводит это окно на передний план и может превратить его в фокусное окно".

Ответ 11

Чтобы избежать потери фокуса окна, когда его возвращение в видимое после того, как оно было скрыто, все, что вам нужно:

setExtendedState(JFrame.NORMAL);

Так же:

defaultItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                showWindow();
                setExtendedState(JFrame.NORMAL);
            }
});