[英]How to bring a window to the front?
當遠程控制機制激活應用程序中的某些內容時,我們需要將Java應用程序帶到前台。
為了得到這個,我們在類的被調用方法中實現了代表我們的應用程序的框架( JFrame
擴展)在實現之后:
setVisible(true);
toFront();
在Windows XP下,這在第一次調用時工作,第二次只有任務欄中的選項卡閃爍,框架不再出現在前面。 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
設置為始終保持在頂部,並為setAlwaysOnTop(false)
提供windowDeactivated
事件處理程序。
因此,這里是可以放入基礎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()
。
請注意,應始終在EDT上調用方法setVisible()
。
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開始,這段代碼似乎運行正常。
這是一種真正有效的方法(在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();
}
}
});
}
我測試了你的答案,只有Stefan Reich的一個為我工作。 雖然我無法將窗口恢復到以前的狀態(最大化/正常)。 我發現這個突變更好:
view.setState(java.awt.Frame.ICONIFIED);
view.setState(java.awt.Frame.NORMAL);
這是setState
而不是setExtendedState
。
最簡單的方法我發現跨平台沒有不一致性:
調用setVisible(假); 調用setVisible(真);
管理.toFront()JFrame時發生的事情的規則在windows和linux中是相同的:
- >如果現有應用程序的窗口當前是焦點窗口,則焦點交換到請求的窗口 - >如果沒有,窗口只會在任務欄中閃爍
但是:
- >新窗口自動獲得焦點
所以讓我們利用這個! 你想給前面帶一個窗口,怎么做? 好 :
或者,在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);
}
});
為了避免窗口在被隱藏后返回可見時失去焦點所需要的是:
setExtendedState(JFrame.NORMAL);
像這樣:
defaultItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showWindow();
setExtendedState(JFrame.NORMAL);
}
});
對於toFront()方法,javadoc中有許多警告可能會導致您的問題。
但無論如何,當“只有任務欄中的選項卡閃爍”時,我會猜測應用程序是否已最小化? 如果是這樣,javadoc的以下行可能適用:
“如果此窗口可見,則將此窗口置於前面,並使其成為焦點窗口。”
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.