Ön tarafa pencere nasıl getirilir?


90

Bir telekontrol mekanizması uygulamadaki bir şeyi etkinleştirdiğinde ön plana çıkarılması gereken bir Java uygulamamız var.

Bunu elde etmek için, JFrameaşağıdaki uygulamamızın çerçevesini (a'nın uzantısı ) temsil eden sınıfın çağrılan yöntemini gerçekleştirdik:

setVisible(true);
toFront();

Windows XP'de bu, ilk çağrıldığında çalışır, ikinci seferde yalnızca görev çubuğundaki sekme yanıp söner, çerçeve artık öne gelmez. Aynı Win2k için de geçerli. Vista'da iyi çalışıyor gibi görünüyor.

Hiç fikrin var mı?


bu davranış için bir örnek var mı?
OscarRyz

3
Doğru cevap, toFront()EDT'yi kullanarak aramaktır invokeLater. Aşağıda verilen basit bir cevap var, ancak kabul edilen cevap bu değil. Yine de çalışıyor. Kusursuzca.
Erick Robertson

Bunun eski olduğunu biliyorum, ancak bu OSX'te de oluyor
ferdil

Bu sorunu yaşıyorum, ancak aşağıdaki yanıtlardan hiçbiri sorunu çözmüyor. Eminim bu, uygulamadaki ilk pencerem için Odağı 'Çalmama' izin vermeyen pencerelerden kaynaklanmaktadır.
Craig Warren

Yanıtlar:


69

Olası bir çözüm:

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

8
Belki de birisi ilk etapta invokeLater içindeki TÜM UI kodunu başlatmalı? ;)
java.is.for.desktop.indeed

2
KDE 4.9.5'teki Java 7'de benim için çalışmadı, pencere yine de diğer programların altında gizleniyordu. Bana yardım eden şey, pencereleri öne getirme sırasını değiştirmekti. Bir pencereyi gizlemek ve ikinci pencereyi göstermek yerine, ikinci pencereyi gösterin ve ardından ilk pencereyi (JFrame) gizleyin.
Lekensteyn

1
Bir uygulamada Java 1.8 çalıştıran Windows 10 ile çalışır
Elliott

Ters yöntem ne olurdu?
Kardinal - Monica'yı yeniden

33

JFrameUbuntu (Java 1.6.0_10) altında bir öne getirirken aynı sorunu yaşadım. Ve bunu çözebilmemin tek yolu bir WindowListener. Spesifik olarak, JFrameher toFront()çağrıldığında her zaman en üstte kalacak şekilde benim ayarlamam ve windowDeactivatedolay işleyicisi sağlamam gerekiyordu setAlwaysOnTop(false).


İşte JFrametüm uygulama çerçevelerini türetmek için kullanılan bir tabana yerleştirilebilecek kod .

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

Çerçeveniz ne zaman gösterilmeli veya ön görüşmeye getirilmelidir frame.setVisible(true).

Ubuntu 9.04'e taşındığımdan beri , görüldüğü gibi WindowListenerçağırmak için bir a sahip olmaya gerek yok gibi görünüyor super.setAlwaysOnTop(false); bu kod yöntemlere taşındı toFront()ve setVisible().

Lütfen bu yöntemin setVisible()her zaman EDT'de çalıştırılması gerektiğini unutmayın .


Teşekkürler! Ayrıca şu soruyla da ilgili: stackoverflow.com/questions/2315560/…
rogerdpack

SetDisposed () yöntemi nedeniyle benim tarafımdan derlenmiyor. Bulunamıyor.
ka3ak

1
@ ka3ak Bu, çerçeve yerleştirilmiş durumdayken durumu izlemek için önerilen JFrame temel sınıfında kullanılabilecek korumalı bir ayarlayıcıdır. Dispose () yönteminin setDisposed (true) çağrısıyla geçersiz kılınması gerekir. Bu kesinlikle herkes için gerekli değildir.
01es

1
.setAlwaysOnTop(true);Bir JWindow kullanırken benim için çalıştı tek kişiydi.
DGolberg

setAlwaysOnTop(true)onu Windows 10 altında çalıştırmamın tek yolu - teşekkürler!
Hartmut P.

23

Windows, pencerelerin odağı çalmasını engelleme özelliğine sahiptir; bunun yerine görev çubuğu simgesini yanıp söner. XP'de varsayılan olarak açıktır (bunu değiştirmek için gördüğüm tek yer TweakUI kullanıyor, ancak bir yerde bir kayıt defteri ayarı var). Vista'da varsayılanı değiştirmiş olabilirler ve / veya kutudan çıkar çıkmaz UI ile kullanıcı tarafından erişilebilen bir ayar olarak sunmuş olabilirler.

Pencerelerin kendilerini öne doğru zorlamasını ve odaklanmasını önlemek, Windows 2K'dan beri bir özellik (ve bunun için minnettarım).

Bununla birlikte, çalışırken aktivitelerimi kaydetmemi hatırlatmak için kullandığım küçük bir Java uygulamam var ve her 30 dakikada bir aktif pencere yapıyor (tabii ki yapılandırılabilir). Windows XP altında her zaman tutarlı bir şekilde çalışır ve başlık çubuğu penceresini hiçbir zaman yanıp sönmez. Bir timer olayı tetiklemesinin bir sonucu olarak UI iş parçacığında çağrılan aşağıdaki kodu kullanır:

if(getState()!=Frame.NORMAL) { setState(Frame.NORMAL); }
toFront();
repaint();

(küçültüldüğünde ilk satır geri yüklenir ... aslında büyütüldüğünde onu da geri yüklerdi, ama ben buna asla sahip değilim).

Genelde bu uygulamayı küçülttüğüm halde, çoğu zaman metin editörümün arkasında. Ve dediğim gibi, her zaman işe yarar.

Probleminizin ne olabileceğine dair bir fikrim var - belki de setVisible () çağrısıyla bir yarış durumunuz var. toFront (), çağrıldığında pencere gerçekten görüntülenmedikçe geçerli olmayabilir; Bu sorunu daha önce requestFocus () ile yaşadım. ToFront () çağrısını, pencere tarafından etkinleştirilen bir olaydaki bir UI dinleyicisine koymanız gerekebilir.

2014-09-07: Bir noktada, yukarıdaki kod çalışmayı durdurdu, belki Java 6 veya 7'de. Biraz araştırma ve denemeden sonra, pencerenin toFrontyöntemini geçersiz kılmak için kodu güncellemem gerekiyordu (değiştirilmiş kodla birlikte yukarıda):

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'den itibaren, bu kod iyi çalışıyor gibi görünüyor.


1
Pencerelerin odağı çalmasına izin vermemesi için +1. Bir belge yazarken bunun olmasından nefret ediyorum.
Ken Paul

1
Odak çalmaya karşı tamamen size katılıyorum, ancak bu kesin durumda kullanıcı uygulamanın öne çıkmasını bekler. Ancak kayıt defteri ayarlarını değiştirmek ve tüm Windows davranışını değiştirmek hoş olmazdı.
boutta

Tahmin ediyorum super.setAlwaysOnTop(false);ki, pencere her zaman üstte olmayacak true, pencereyi öne getirmek için daha önce belirlediğimizden kurtulmak için gerekli , değil mi? Soruyorum çünkü kodunuzla pencere hala benim durumumda her zaman en üstte, ki bunu kesinlikle istemiyorum. Windows 10'da jre1.8.0_66 çalıştırılıyor
Bram Vanroy

@Bram: Evet bu doğru. Kodu Java ve Windows'un aynı sürümünde çalıştırıyorum ve her zaman diğer pencerelerin üstünde bitmiyor. Her zaman en üstte ayarlamak gerekli olmayabilir, ancak sanırım aksi takdirde Windows, en azından bazı koşullar altında başlık çubuğunu yanıp söner.
Lawrence Dol

Hm, tuhaf. Bu yanıta bağladığım benzer bir soruya bir göz atabilir misiniz? Belki bu kod sorunu daha net gösteriyor: stackoverflow.com/questions/34637597/…
Bram Vanroy

11

İşte GERÇEKTEN işe yarayan bir yöntem (Windows Vista'da test edilmiştir): D

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

Tam ekran değişkeni, uygulamanın tam ekran mı yoksa pencereli mi çalışmasını istediğinizi belirtir.

Bu, görev çubuğunu yanıp sönmez, ancak pencereyi güvenilir bir şekilde öne getirir.


SetExtendedState ipucu için teşekkürler. Pencereyi simge durumuna küçültülmüş olsa bile ön plana getirmek için toFront () ve repaint () çözümüyle birlikte kullandım.
soymak

1
Onaylandı: Bu çözüm WindowsXP'de çalışır, toFront'un kullanılması görev çubuğunda yanıp sönen mesajla sonuçlanır. Teşekkürler!
Eric Lindauer

5

Hj, Fedora KDE 14'te sizin tüm yöntemlerim benim için çalışmıyor. Oracle'ın bu sorunu çözmesini beklerken, bir pencereyi öne çıkarmanın kirli bir yolu var.

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

  //...

}

Ve bu benim Fedora KDE 14'te mükemmel çalışıyor :-)


Biraz hantal, bizim için işe yarıyor, ancak yalnızca ilk arama için :-). (Kubuntu 12.04) - diğer çözüm başarısız oldu
user85155

Bu, bir JFrame'in (oturum açma) açıldığı, ancak kullanıcı tıklayana kadar odaklanmadığı bir sorun için benim için çalışan tek çözümdü (Windows Server 2012 R2).
glenneroo

4

Bu basit yöntem benim için Windows 7'de mükemmel çalıştı:

    private void BringToFront() {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                if(jFrame != null) {
                    jFrame.toFront();
                    jFrame.repaint();
                }
            }
        });
    }

2
repaint()Gerekli değil, invokeLater()bunu yaptı. Teşekkür ederim.
Matthieu

4

Cevaplarınızı test ettim ve sadece Stefan Reich benim için çalıştı. Pencereyi önceki durumuna (maksimize edilmiş / normal) geri yükleyemememe rağmen. Bu mutasyonu daha iyi buldum:

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

Bunun setStateyerine setExtendedState.


3

Platformlar arasında tutarsızlığın olmadığını bulduğum en basit yol:

setVisible (yanlış); setVisible (doğru);


1
bazılarının göz kırpmasına neden oluyor, değil mi? güzel ve basit ama :)
rogerdpack

arka plan sürecim için işe yaramadı. Ayrıca ön plan işleminden çağrılırsa pencere ilk yenileme için beyaz olarak gelir. Ekran kapmak için kullanılamaz.
DragonLord

pencerenin simge
haline gelip gelmediğini

2

Bir JFrame .toFront () kullandığınızda ne olacağını belirleyen kurallar Windows ve Linux'ta aynıdır:

-> mevcut uygulamanın bir penceresi şu anda odaklanılan pencereyse, odak istenen pencereye geçer -> değilse, pencere yalnızca görev çubuğunda yanıp söner

FAKAT :

-> yeni pencereler otomatik olarak odaklanır

Öyleyse bundan yararlanalım! Ön tarafa bir pencere açmak istiyorsun, nasıl yapmalı? İyi :

  1. Amacı olmayan boş bir pencere oluşturun
  2. Göster
  3. Ekranda görünmesini bekleyin (setVisible bunu yapar)
  4. Gösterildiğinde, gerçekten odağı getirmek istediğiniz pencere için odak isteyin.
  5. boş pencereyi sakla, yok et

Veya java kodunda:

// 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'de çalışmadı, her iki pencere de yanıp sönüyor (2.'yi gizlemezsem).
kabaetler

Yaratıcı. Örtüldüğünde, Win7'deki arka plan işlemim için işe yaramadı. Yeni çerçeve üstte gelmiyor. Eski JDK 6u21.
DragonLord

0

Çok sayıda uyarı varToFront () yöntemi için javadoc'ta sorununuza neden olabilecek .

Ama yine de bir tahminde bulunacağım, "sadece görev çubuğundaki sekme yanıp söndüğünde", uygulama küçültüldü mü? Eğer öyleyse, javadoc'tan aşağıdaki satır geçerli olabilir:

"Bu Pencere görünüyorsa, bu Pencereyi öne getirir ve onu odaklanmış Pencere yapabilir."


0

Pencerenin, gizlendikten sonra görünür hale döndüğünde odağı kaybetmesini önlemek için gereken tek şey şudur:

setExtendedState(JFrame.NORMAL);

Şöyle:

defaultItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                showWindow();
                setExtendedState(JFrame.NORMAL);
            }
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.