質問
テレコントロールメカニズムがアプリケーション内の何かをアクティブにしたときにフォアグラウンドに移動する必要があるJavaアプリケーションがあります。
これを取得するために、実装の次のアプリケーションのフレーム( JFrame
の拡張)を表すクラスの呼び出されたメソッドで実現しました:
setVisible(true);
toFront();
Windows XPでは、これは最初に呼び出されたときに機能し、2回目にはタスクバーのタブのみが点滅し、フレームが前面に表示されなくなります。 Win2kについても同様です。 Vistaでは正常に動作するようです。
アイデアはありますか?
解決
可能な解決策は次のとおりです。
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
myFrame.toFront();
myFrame.repaint();
}
});
他のヒント
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で呼び出す必要があることに注意してください。
Windowsには、ウィンドウがフォーカスを奪うのを防ぐ機能があります。代わりに、タスクバーアイコンが点滅します。 XPではデフォルトでオンになっています(変更を確認した唯一の場所はTweakUIの使用ですが、どこかにレジストリ設定があります)。 Vistaでは、デフォルトを変更したり、すぐに使用できるUIでユーザーがアクセス可能な設定として公開したりする可能性があります。
Windowsが前面に強制的に移動してフォーカスを取得するのを防ぐことは、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で上記のコードが機能しなくなりました。いくつかの調査と実験の後、コードを更新してウィンドウの< 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);
fullscreen変数は、アプリを全画面で実行するかウィンドウ表示するかを示します。
これはタスクバーをフラッシュしませんが、ウィンドウを確実に前面に表示します。
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();
}
}
});
}
回答をテストしましたが、 Stefan Reichの回答のみをテストしました私のために働いた。ウィンドウを以前の状態(最大化/通常)に復元することはできませんでしたが。私はこの突然変異をよりよく見つけました:
view.setState(java.awt.Frame.ICONIFIED);
view.setState(java.awt.Frame.NORMAL);
それは setExtendedState
ではなく setState
です。
プラットフォーム間で矛盾がないことがわかった最も簡単な方法:
setVisible(false); setVisible(true);
JFrameを.toFront()した場合の動作を管理するルールは、WindowsとLinuxで同じです:
-&gt;既存のアプリケーションのウィンドウが現在フォーカスされているウィンドウである場合、フォーカスは要求されたウィンドウにスワップします -&gt;そうでない場合、ウィンドウは単にタスクバーで点滅します
しかし:
-&gt;新しいウィンドウは自動的にフォーカスを取得します
これを活用しましょう!窓を前面に持ってきたいのですが、どうすればいいですか?さて:
- 空の非目的ウィンドウを作成する
- 表示
- 画面に表示されるのを待ちます(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);
}
});
多数の警告 javadocのtoFront()メソッドで問題が発生している可能性があります。
しかし、とにかく「タスクバーのタブのみが点滅する」場合、アプリケーションは最小化されていますか?その場合、javadocの次の行が適用される可能性があります。
&quot;このウィンドウが表示されている場合、このウィンドウを前面に移動し、フォーカスされたウィンドウにすることができます。
ウィンドウが非表示になった後に可視状態に戻ったときにフォーカスが失われないようにするために必要なものは次のとおりです。
setExtendedState(JFrame.NORMAL);
そのように:
defaultItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showWindow();
setExtendedState(JFrame.NORMAL);
}
});