web-dev-qa-db-ja.com

ウィンドウを前面に移動する方法は?

Javaアプリケーションがあります。このアプリケーションは、テレコントロールメカニズムがアプリケーション内で何かをアクティブにしたときにフォアグラウンドに移動する必要があります。

これを取得するために、実装の次のアプリケーションのフレーム(JFrameの拡張)を表すクラスの呼び出されたメソッドで実現しました。

setVisible(true);
toFront();

Windows XPでは、これは最初に呼び出されたときに機能し、2回目にはタスクバーのタブのみが点滅し、フレームが前面に表示されなくなります。 Win2kについても同様です。 Vistaでは正常に動作するようです。

あなたはなにか考えはありますか?

87
boutta

Ubuntu(Java 1.6.0_10)の下でJFrameを前面に持ってくるのと同じ問題がありました。そして、それを解決できる唯一の方法は、WindowListenerを提供することです。具体的には、toFront()が呼び出されたときは常にJFrameが常にトップになるように設定し、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に移行したので、super.setAlwaysOnTop(false)を呼び出すためにWindowListenerを用意する必要はないようです。このコードはtoFront()およびsetVisible()メソッドに移動されました。

メソッドsetVisible()はEDTで常に呼び出されることに注意してください。

33
01es

Windowsには、ウィンドウがフォーカスを奪うのを防ぐ機能があります。代わりに、タスクバーアイコンが点滅します。 XPこれはデフォルトでオンになっています(変更を確認した唯一の場所はTweakUIを使用していますが、どこかにレジストリ設定があります)。Vistaではデフォルトおよび/またはすぐに使えるUIでユーザーがアクセスできる設定として公開しました。

ウィンドウが前面に強制的に移動してフォーカスを取得するのを防ぐことは、Windows 2Kの機能です(私は感謝しています)。

つまり、作業中にアクティビティを記録するように思い出させるために使用するアプリは少しJavaであり、それ自体が30分ごとにアクティブウィンドウになります(もちろん構成可能)。一貫してWindows XPであり、タイトルバーウィンドウをフラッシュしません。タイマーイベントの起動の結果としてUIスレッドで呼び出される次のコードを使用します。

if(getState()!=Frame.NORMAL) { setState(Frame.NORMAL); }
toFront();
repaint();

(最小化された場合、最初の行が復元されます...実際に最大化された場合も復元されますが、私はそうしません)。

私は通常、このアプリを最小化していますが、かなり頻繁にテキストエディタの背後にあります。そして、私が言ったように、それは常に機能します。

私はあなたの問題が何であるかについてのアイデアを持っています-おそらくあなたはsetVisible()呼び出しで競合状態を持っているでしょう。 toFront()は、ウィンドウが呼び出されたときに実際に表示されない限り有効ではない場合があります。以前にrequestFocus()でこの問題が発生しました。ウィンドウ起動イベントのUIリスナーに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の時点で、このコードは正常に機能しているようです。

22
Lawrence Dol

これは本当に機能するメソッドです(Windows Vistaでテスト済み):D

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

Fullscreen変数は、アプリを全画面で実行するかウィンドウ表示するかを示します。

これはタスクバーをフラッシュしませんが、ウィンドウを確実に前面に表示します。

11
Stefan Reich

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で完璧に動作します:-)

5
user942821

この単純な方法は、Windows 7で完璧に機能しました。

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

私はあなたの答えをテストしました ステファンライヒのもの 私のために働いた。ウィンドウを以前の状態(最大化/通常)に復元することはできませんでしたが。私はこの突然変異をよりよく見つけました:

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

これは、setStateではなくsetExtendedStateです。

4
Jarekczek

プラットフォーム間で矛盾がない、私が見つけた最も簡単な方法:

setVisible(false); setVisible(true);

3
Rich

JFrameを.toFront()した場合の動作を管理するルールは、WindowsとLinuxで同じです:

->既存のアプリケーションのウィンドウが現在フォーカスされているウィンドウである場合、要求されたウィンドウにフォーカスがスワップします->そうでない場合、ウィンドウは単にタスクバーで点滅します

しかし:

->新しいウィンドウが自動的にフォーカスを取得します

これを活用しましょう!窓を前面に持ってきたいのですが、どうすればいいですか?まあ:

  1. 空の非目的ウィンドウを作成する
  2. それを示す
  3. 画面に表示されるまで待ちます(setVisibleはそれを行います)
  4. 表示されたら、実際にフォーカスを移動したいウィンドウのフォーカスを要求します
  5. 空のウィンドウを非表示にし、破棄します

または、Java code:

// 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);
  }
});
2
christopher

ToFront()メソッドのjavadocには、問題を引き起こしている可能性のある 警告 が多数あります。

しかし、とにかく「タスクバーのタブのみが点滅する」場合、アプリケーションは最小化されていますか?その場合、javadocの次の行が適用されます。

「このウィンドウが表示されている場合、このウィンドウを前面に移動し、フォーカスされたウィンドウにすることができます。」

0
Brendan Cashman

隠された後に可視状態に戻ったときにウィンドウがフォーカスを失うのを避けるために必要なことは次のとおりです。

setExtendedState(JFrame.NORMAL);

そのようです:

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