窓を前面に出すには?


90

遠隔制御メカニズムがアプリケーション内の何かをアクティブ化するときにフォアグラウンドに移動する必要があるJavaアプリケーションがあります。

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

setVisible(true);
toFront();

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

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


この動作のサンプルはありますか?
OscarRyz 2008

3
適切な答えはtoFront()、を使用してEDTを呼び出すことinvokeLaterです。以下に含まれる簡単な答えがありますが、受け入れられた答えではありません。ただし、機能します。完璧に。
エリックロバートソン、

私はこれが古いことを知っていますが、これはOSXでも発生します
ferdil

私はこの問題を経験していますが、以下の回答のどれもそれを解決しないようです。アプリケーションの最初のウィンドウでフォーカスを「スチール」できないウィンドウが原因であると確信しています。
クレイグウォーレン

回答:


69

可能な解決策は次のとおりです。

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

8
おそらく、最初にinvokeLater内のすべてのUIコードを開始する必要がありますか?;)
java.is.for.desktop.indeed 2011

2
KDE 4.9.5上のJava 7では私にとっては機能しませんでしたが、ウィンドウは他のプログラムの下に隠れます。私を助けたのは、窓を前面に出す順序を変更することでした。1つのウィンドウを非表示にして2番目のウィンドウを表示する代わりに、2番目のウィンドウを表示してから、最初のウィンドウ(JFrame)を非表示にします。
Lekensteyn 2013年

1
アプレットでJava 1.8を実行しているWindows 10で動作します
Elliott

逆の方法は何でしょうか?
枢機卿-モニカを

33

JFrameUbuntu(Java 1.6.0_10)の下でa を前面に持ってくることで同じ問題がありました。そして、私がそれを解決できる唯一の方法は、を提供することですWindowListener。具体的には、が呼び出さJFrameれても常にトップに留まるように設定し、にイベントハンドラーをtoFront()提供する必要がありwindowDeactivatedましたsetAlwaysOnTop(false)


したがって、JFrameすべてのアプリケーションフレームを派生させるために使用されるbase に配置できるコードは次のとおりです。

@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/...
rogerdpack

setDisposed()メソッドが原因で、私はコンパイルできません。見つかりません。
ka3ak 2013年

1
@ ka3akこれは、フレームが破棄される状況を追跡するために、提案されたJFrameベースクラスに導入できる保護されたセッターです。メソッドdispose()は、setDisposed(true)の呼び出しでオーバーライドする必要があります。これは厳密に言えば誰にとっても必要なことではありません。
01es 2013年

1
.setAlwaysOnTop(true);JWindowを使用するときに私のために機能したのはこれだけでした。
DGolberg 2014

setAlwaysOnTop(true)Windows 10で実行する唯一の方法です。ありがとうございます。
Hartmut P.

22

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

ウィンドウが自分自身を前面に押し込んでフォーカスを取得するのを防ぐことは、Windows 2K以降の機能です(私は1つは感謝しています)。

とは言っても、作業中に自分のアクティビティを記録するように通知するために使用する小さな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以降、このコードは正常に動作しているようです。


1
ウィンドウがフォーカスを盗むことを許可しないことをサポートするための+1。ドキュメントを入力しているときにそうなるのは嫌です。
ケン・ポール

1
フォーカスを盗むことについては完全に同意しますが、この場合、ユーザーはアプリケーションが前面に来ることを期待しています。しかし、レジストリ設定を変更し、完全なウィンドウの動作を変更するのはクールではありません。
boutta 2008年

super.setAlwaysOnTop(false);はこれがウィンドウが常に上になるとは限らないのでtrue、前に設定したウィンドウを前面に表示するために削除する必要があると思いますか?私の質問では、あなたのコードではウィンドウが常に一番上にあるので、私は明らかに望んでいません。Windows 10でjre1.8.0_66を実行
Bram Vanroy

@ブラム:そうだね。同じバージョンのJavaとWindowsでコードを実行していますが、他のウィンドウの上に常に表示されるわけではありません。常に上に設定する必要はないかもしれませんが、そうでなければ、少なくともいくつかの条件下では、Windowsがタイトルバーを点滅させるだけだと思います。
ローレンスドル

ふむ、変。私がこの回答にリンクしている同様の質問を見てください。たぶん、そのコードが示すより明確な問題:stackoverflow.com/questions/34637597/...
ブラムVanroy

11

これが実際に機能する方法です(Windows Vistaでテスト済み)。

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

fullscreen変数は、アプリをフルスクリーンで実行するか、ウィンドウで実行するかを示します。

これはタスクバーを点滅させませんが、ウィンドウを確実に前面に表示します。


setExtendedStateのヒントをありがとう。これをtoFront()およびrepaint()ソリューションと一緒に使用して、最小化されている場合でもウィンドウを前面に表示しました。
rob

1
確認済み:このソリューションはWindowsXPで機能し、toFrontを使用するとタスクバーにメッセージが点滅します。ありがとう!
エリックリンダウアー2012年

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


少しハッキーですが、私たちにとってはうまくいきますが、最初の呼び出しのみです:-)。(Kubuntu 12.04)-他のソリューションが失敗しました
user85155 '21

これは、JFrame(ログイン)が開いているがユーザーがクリックするまでフォーカスがないという問題に対して私(Windows Server 2012 R2)で機能した唯一のソリューションでした。
glenneroo 2016年

4

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

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

2
repaint()、必要はありませんinvokeLater()それをやりました。ありがとうございました。
Matthieu

4

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

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

それはのsetState代わりですsetExtendedState


3

プラットフォーム間で矛盾がないことがわかった最も簡単な方法:

setVisible(false); setVisible(true);


1
いくつかの点滅を引き起こしませんか?素敵でシンプルですが:)
rogerdpack

私のバックグラウンドプロセスでは機能しませんでした。また、フォアグラウンドプロセスから呼び出された場合、最初の更新時にウィンドウが白くなります。画面グラブには使用できません。
DragonLord、2014年

ウィンドウがアイコン化されているかどうかを確認することで、点滅を回避できます
totaam

2

JFrameを.toFront()したときに何が起こるかを管理するルールは、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);
  }
});

Win7では動作しませんでした。両方のウィンドウが点滅します(2番目を非表示にしない場合)。
NateS 2013

クリエイティブ。カバーされている場合、Win7でのバックグラウンドプロセスでは機能しませんでした。新しいフレームが上に表示されません。古いJDK 6u21。
DragonLord、2014年

0

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

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

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


0

ウィンドウが非表示になった後に表示に戻ったときにフォーカスが失われるのを防ぐには、必要なのは次のとおりです。

setExtendedState(JFrame.NORMAL);

そのようです:

defaultItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                showWindow();
                setExtendedState(JFrame.NORMAL);
            }
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.