簡體   English   中英

如何將窗戶拉到前面?

[英]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中是相同的:

- >如果現有應用程序的窗口當前是焦點窗口,則焦點交換到請求的窗口 - >如果沒有,窗口只會在任務欄中閃爍

但是:

- >新窗口自動獲得焦點

所以讓我們利用這個! 你想給前面帶一個窗口,怎么做? 好 :

  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);
  }
});

為了避免窗口在被隱藏后返回可見時失去焦點所需要的是:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM