Вопрос

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

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

setVisible(true);
toFront();

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

Есть ли у вас какие-либо идеи?

Это было полезно?

Решение

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

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

Другие советы

У меня была та же проблема с переносом JFrame на фронт под Ubuntu (Java 1.6.0_10). И единственный способ решить эту проблему - предоставить WindowListener . В частности, я должен был установить свой JFrame так, чтобы он всегда оставался на вершине при каждом вызове toFront () , и предоставлял обработчик события windowDeactivation для setAlwaysOnTop (ложь) . <Ч>

Итак, вот код, который можно поместить в базовый 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.

В 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. После некоторых исследований и экспериментов мне пришлось обновить код, чтобы переопределить окно < Метод code> 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();
                }
            }
        });
    }

Я проверил ваши ответы и только ответ Стефана Райха у меня сработало. Хотя мне не удалось восстановить окно к его предыдущему состоянию (развернуто / нормально). Я нашел эту мутацию лучше:

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

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

Самый простой способ, который я нашел, не имеет противоречий на разных платформах:

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

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

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

НО :

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

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

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

Или в 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);
            }
});
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top