93

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

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

setVisible(true);
toFront();

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

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

4

11 に答える 11

70

考えられる解決策は次のとおりです。

java.awt.EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        myFrame.toFront();
        myFrame.repaint();
    }
});
于 2008-12-22T21:09:37.293 に答える
35

JFrameUbuntu (Java 1.6.0_10) でa を前面に出す際にも同じ問題がありました。そして、私がそれを解決できる唯一の方法は、WindowListener. 具体的には、が呼び出さJFrameれるたびに常に最上位に留まるようにmy を設定し、 にイベント ハンドラーを提供する必要がありました。toFront()windowDeactivatedsetAlwaysOnTop(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)

WindowListener私はUbuntu 9.04に移行して以来、呼び出すための必要はないようですsuper.setAlwaysOnTop(false)-観察できるように; このコードは、メソッドtoFront()とに移動されましたsetVisible()

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

于 2009-02-27T19:01:40.800 に答える
23

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 の時点で、このコードは正常に動作しているようです。

于 2008-11-22T03:25:00.563 に答える
12

これは本当に機能する方法です(Windows Vistaでテスト済み):D

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

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

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

于 2011-09-15T18:33:32.073 に答える
5

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

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

それはsetStateの代わりですsetExtendedState

于 2012-03-09T13:27:16.780 に答える
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で完全に機能します:-)

于 2011-09-13T15:21:51.107 に答える
4

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

    private void BringToFront() {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                if(jFrame != null) {
                    jFrame.toFront();
                    jFrame.repaint();
                }
            }
        });
    }
于 2011-05-10T14:38:48.607 に答える
3

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

setVisible(偽); setVisible(真);

于 2010-11-02T15:41:50.783 に答える
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);
  }
});
于 2011-06-24T15:11:47.593 に答える
1

ウィンドウが非表示になった後に表示に戻ったときにフォーカスが失われないようにするには、次のことを行う必要があります。

setExtendedState(JFrame.NORMAL);

そのようです:

defaultItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                showWindow();
                setExtendedState(JFrame.NORMAL);
            }
});
于 2014-12-30T20:55:07.320 に答える
0

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

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

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

于 2008-11-21T15:23:00.363 に答える