창문을 앞으로 가져 오는 방법?


90

원격 제어 메커니즘이 애플리케이션에서 무언가를 활성화 할 때 포 그라운드로 가져와야하는 Java 애플리케이션이 있습니다.

이를 얻기 위해, 우리는 애플리케이션의 프레임 (확장자 JFrame) 을 나타내는 클래스의 호출 된 메서드에서 다음 구현을 깨달았습니다 .

setVisible(true);
toFront();

Windows XP에서는 처음 호출 될 때 작동하고 두 번째로 작업 표시 줄의 탭만 깜박이고 프레임이 더 이상 앞으로 나오지 않습니다. Win2k도 마찬가지입니다. Vista에서는 잘 작동하는 것 같습니다.

아이디어가 있습니까?


이 동작에 대한 샘플이 있습니까?
OscarRyz

3
올바른 대답 toFront()은를 사용하여 EDT 를 호출 하는 것 invokeLater입니다. 아래에 간단한 답변이 포함되어 있지만 허용되는 답변이 아닙니다. 그래도 작동합니다. 아주.
Erick Robertson

나는 이것이 오래 알고 있지만,이 또한 OSX에서 발생
ferdil

이 문제가 발생했지만 아래 답변 중 어느 것도 해결되지 않는 것 같습니다. 나는 그것이 응용 프로그램의 첫 번째 창에 대해 'Steal'Focus를 허용하지 않는 창 때문이라고 확신합니다.
Craig Warren

답변:


69

가능한 해결책은 다음과 같습니다.

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

8
아마도 invokeLater 내의 모든 UI 코드를 처음부터 시작해야할까요? )
java.is.for.desktop.indeed

2
KDE 4.9.5의 Java 7에서 나를 위해 작동하지 않았지만 창이 여전히 다른 프로그램 아래에 숨겨져 있습니다. 내게 도움이 된 것은 창문을 앞으로 가져 오는 순서를 바꾸는 것이 었습니다. 하나의 창을 숨기고 두 번째 창을 표시하는 대신 두 번째 창을 표시 한 다음 첫 번째 창 (JFrame)을 숨 깁니다.
Lekensteyn 2013 년

1
애플릿에서 Java 1.8을 실행하는 Windows 10에서 작동
Elliott

역 방법은 무엇입니까?
추기경-Monica 복원

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) .

우분투 9.04로 옮긴 이후 로 볼 수 있듯이 WindowListener호출을위한를 가질 필요가없는 것 같습니다 super.setAlwaysOnTop(false). 이 코드는 메서드로 이동 toFront()되었으며setVisible() .

메서드 setVisible()는 항상 EDT에서 호출되어야합니다.


감사! 또한이 질문과 관련이 있습니다 : stackoverflow.com/questions/2315560/…
rogerdpack 2010-08-18

setDisposed () 메서드 때문에 나에 의해 컴파일되지 않습니다. 찾을 수 없습니다.
ka3ak 2013 년

1
@ ka3ak 프레임이 삭제 된 상황을 추적하기 위해 제안 된 JFrame 기반 클래스에 도입 될 수있는 보호 된 setter입니다. 메서드 dispose ()는 setDisposed (true)에 대한 호출로 재정의되어야합니다. 이것은 모든 사람에게 엄격히 필요한 것은 아닙니다.
01es mar

1
.setAlwaysOnTop(true);JWindow의를 사용할 때 나를 위해 일한 유일한 사람이었다.
DGolberg

setAlwaysOnTop(true)Windows 10에서 실행되는 유일한 방법입니다. 감사합니다!
Hartmut P.

23

Windows에는 창이 초점을 훔치는 것을 방지하는 기능이 있습니다. 대신 작업 표시 줄 아이콘이 깜박입니다. XP에서는 기본적으로 켜져 있습니다 (제가 변경 한 유일한 곳은 TweakUI를 사용하는 것이지만 어딘가에 레지스트리 설정이 있습니다). Vista에서는 기본 UI를 사용하여 기본값을 변경하거나 사용자가 액세스 할 수있는 설정으로 노출했을 수 있습니다.

윈도우 2K 이후로 윈도우가 강제로 앞쪽으로 향하는 것을 방지하고 초점을 맞추는 기능은 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부터이 코드는 제대로 작동하는 것 같습니다.


1
창문이 초점을 훔치지 못하도록 지원하는 +1. 문서를 입력 할 때 그런 일이 발생하는 것이 싫습니다.
Ken Paul

1
나는 초점을 훔치는 것에 대해 전적으로 동의하지만이 정확한 경우 사용자는 응용 프로그램이 앞으로 나올 것으로 기대합니다. 그러나 레지스트리 설정을 변경하고 전체 Windows 동작을 변경하는 것은 멋지지 않습니다.
boutta

나는 super.setAlwaysOnTop(false);창문이 항상 맨 위에 있지 않기 때문에true 창을 앞으로 가져 오기 위해 이전에 설정 한 것을 제거하는 데 필요하다고 생각합니다. 맞습니까? 귀하의 코드를 사용하면 창은 내 경우에는 항상 맨 위에 있기 때문에 분명히 원하지 않습니다. Windows 10에서 jre1.8.0_66 실행
Bram Vanroy

@Bram : 네 맞습니다. 동일한 버전의 Java 및 Windows에서 코드를 실행 중이며 항상 다른 창 위에있는 것은 아닙니다. 항상 맨 위에 설정할 필요는 없지만 그렇지 않으면 Windows가 적어도 일부 조건에서 제목 표시 줄을 깜박입니다.
Lawrence Dol

흠, 이상합니다. 이 답변에 연결된 비슷한 질문을 살펴볼 수 있습니까? 어쩌면 그 코드 쇼 더 명확하게 문제 : stackoverflow.com/questions/34637597/...
브람 Vanroy

11

다음은 실제로 작동하는 방법입니다 (Windows Vista에서 테스트 됨) .D

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

fullscreen 변수는 앱을 전체 화면으로 실행할 것인지 창으로 실행할 것인지를 나타냅니다.

이것은 작업 표시 줄을 깜박이지 않지만 창을 안정적으로 앞으로 가져옵니다.


setExtendedState 팁에 감사드립니다. toFront () 및 repaint () 솔루션과 함께 사용하여 창을 최소화하더라도 전경으로 가져 왔습니다.
rob

1
확인 됨 :이 솔루션은 WindowsXP에서 작동하며 toFront를 사용하면 작업 표시 줄에 메시지가 깜박입니다. 감사!
Eric Lindauer

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에서 완벽하게 작동합니다. :-)


약간 해키, 우리를 위해 일하지만 첫 번째 호출에만 적용됩니다 :-). (쿠분투 12.04) - 다른 솔루션이 실패 않았다
user85155

이것은 JFrame (로그인)이 열리지 만 사용자가 클릭 할 때까지 포커스가없는 문제에 대해 저 (Windows Server 2012 R2)에게 효과가 있었던 유일한 솔루션이었습니다.
glenneroo

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

나는 당신의 대답을 테스트했고 Stefan Reich의 대답 만이 나를 위해 일했습니다. 창을 이전 상태 (최대화 / 정상)로 복원 할 수는 없었지만. 이 돌연변이가 더 잘 발견되었습니다.

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

setState대신 setExtendedState.


3

플랫폼간에 불일치가없는 가장 간단한 방법은 다음과 같습니다.

setVisible (false); setVisible (true);


1
그래도 약간의 깜박임이 발생하지 않습니까? 좋은 간단 :)하지만
rogerdpack

내 백그라운드 프로세스에서 작동하지 않았습니다. 또한 전경 프로세스에서 호출되면 첫 번째 새로 고침을 위해 창이 흰색으로 표시됩니다. 화면 캡처에 사용할 수 없습니다.
DragonLord

창이 아이콘 화되었는지 확인하여 깜박임을 피할 수 있습니다
totaam

2

JFrame을 .toFront () 할 때 일어나는 일을 제어하는 ​​규칙은 Windows와 Linux에서 동일합니다.

-> 기존 응용 프로그램의 창이 현재 포커스 된 창인 경우 포커스가 요청 된 창으로 바뀝니다.-> 그렇지 않은 경우 창은 작업 표시 줄에서 깜박입니다.

하지만 :

-> 새 창은 자동으로 포커스를받습니다.

그래서 이것을 이용합시다! 창문을 앞으로 가져오고 싶은데 어떻게해야하나요? 음 :

  1. 비어있는 비 목적 창 만들기
  2. 보여
  3. 화면에 표시 될 때까지 기다립니다 (setVisible이 수행합니다).
  4. 표시되면 실제로 포커스를 가져 오려는 창에 포커스를 요청합니다.
  5. 빈 창을 숨기고 파괴

또는 자바 코드에서 :

// 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에서 작동하지 않았고 두 창 모두 깜박입니다 (두 번째 창을 숨기지 않으면).
NateS

창의적. 다루었을 때 Win7의 백그라운드 프로세스에서 작동하지 않았습니다. 새로운 프레임이 위에 나오지 않습니다. 이전 JDK 6u21.
DragonLord

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.