Domanda

Abbiamo un'applicazione Java che deve essere portata in primo piano quando un meccanismo di telecontrollo attiva qualcosa nell'applicazione.

Per ottenere ciò, ci siamo resi conto del metodo chiamato della classe che rappresenta il frame della nostra applicazione (estensione di un JFrame ) dopo l'implementazione:

setVisible(true);
toFront();

In Windows XP, funziona la prima volta che viene chiamato, la seconda volta lampeggia solo la scheda nella barra delle applicazioni, il frame non viene più in primo piano. Lo stesso vale per Win2k. Su Vista sembra funzionare bene.

Hai qualche idea?

È stato utile?

Soluzione

Una possibile soluzione è:

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

Altri suggerimenti

Ho avuto lo stesso problema nel portare un JFrame in primo piano sotto Ubuntu (Java 1.6.0_10). E l'unico modo per risolverlo è fornire un WindowListener . In particolare, ho dovuto impostare il mio JFrame per rimanere sempre in primo piano ogni volta che viene invocato toFront () e fornire il gestore eventi windowDeactivated su setAlwaysOnTop (false) .


Quindi, ecco il codice che potrebbe essere inserito in un JFrame di base, che viene utilizzato per derivare tutti i frame dell'applicazione.

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

Ogni volta che il tuo frame deve essere visualizzato o portato in primo piano frame.setVisible (true) .

Da quando mi sono trasferito su Ubuntu 9.04 non sembra essere necessario avere un WindowListener per invocare super.setAlwaysOnTop (false) - come si può osservare; questo codice è stato spostato nei metodi toFront () e setVisible () .

Si noti che il metodo setVisible () deve sempre essere invocato su EDT.

Windows ha la possibilità di impedire a Windows di rubare il focus; invece lampeggia l'icona della barra delle applicazioni. In XP è attivo di default (l'unico posto che ho visto per cambiarlo è usare TweakUI, ma c'è un'impostazione del registro da qualche parte). In Vista potrebbero aver modificato il valore predefinito e / o averlo esposto come impostazione accessibile all'utente con l'interfaccia utente pronta all'uso.

Impedire a Windows di forzare se stessi in primo piano e attirare l'attenzione è una funzionalità dal momento che Windows 2K (e io, per esempio, ne sono grato).

Detto questo, ho una piccola app Java che uso per ricordarmi di registrare le mie attività mentre lavoro e si rende la finestra attiva ogni 30 minuti (configurabile, ovviamente). Funziona sempre in modo coerente con Windows XP e non lampeggia mai la finestra della barra del titolo. Utilizza il seguente codice, chiamato nel thread dell'interfaccia utente come risultato di un evento timer:

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

(la prima riga viene ripristinata se ridotta a icona ... in realtà la ripristinerebbe anche se ingrandita, ma non la ho mai così).

Mentre di solito ho questa app ridotta a icona, abbastanza spesso è semplicemente dietro il mio editor di testo. E, come ho detto, funziona sempre.

Ho un'idea di quale potrebbe essere il tuo problema - forse hai una condizione di competizione con la chiamata setVisible (). toFront () potrebbe non essere valido a meno che la finestra non sia effettivamente visualizzata quando viene chiamata; Ho avuto questo problema con requestFocus () prima. Potrebbe essere necessario inserire la chiamata toFront () in un listener dell'interfaccia utente in un evento attivato dalla finestra.

2014-09-07: Ad un certo punto il codice sopra ha smesso di funzionare, forse su Java 6 o 7. Dopo qualche indagine e sperimentazione ho dovuto aggiornare il codice per sovrascrivere la finestra < Il metodo code> toFront (in combinazione con il codice modificato rispetto a quanto sopra):

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

A partire da Java 8_20, questo codice sembra funzionare correttamente.

Ecco un metodo che funziona DAVVERO (testato su Windows Vista): D

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

La variabile a schermo intero indica se si desidera eseguire l'app a schermo intero o con finestre.

Questo non lampeggia sulla barra delle applicazioni, ma porta la finestra in primo piano in modo affidabile.

Hj, tutti i tuoi metodi non funzionano per me, in Fedora KDE 14. Ho un modo sporco di portare una finestra in primo piano, mentre stiamo aspettando che Oracle risolva questo problema.

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

  //...

}

E, questo funziona perfettamente nel mio Fedora KDE 14 :-)

Questo semplice metodo ha funzionato perfettamente per me in Windows 7:

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

Ho testato le tue risposte e solo quello di Stefan Reich ha funzionato per me. Anche se non sono riuscito a ripristinare la finestra al suo stato precedente (ingrandito / normale). Ho trovato questa mutazione migliore:

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

Questo è setState invece di setExtendedState .

Ho scoperto il modo più semplice che non presenta incoerenze tra le piattaforme:

setVisible (false); setVisible (true);

Le regole che governano cosa succede quando .toFront () un JFrame sono le stesse in Windows e Linux:

- > se una finestra dell'applicazione esistente è attualmente la finestra attiva, quindi attiva gli swap sulla finestra richiesta - > in caso contrario, la finestra lampeggia semplicemente nella barra delle applicazioni

MA:

- > le nuove finestre diventano automaticamente attive

Quindi sfruttiamolo! Vuoi portare una finestra in primo piano, come si fa? Bene:

  1. Crea una finestra vuota senza scopo
  2. Mostra
  3. Aspetta che appaia sullo schermo (setVisible lo fa)
  4. Quando visualizzato, richiedi lo stato attivo per la finestra in cui desideri effettivamente attivare lo stato
  5. nascondi la finestra vuota, distruggila

O, nel codice 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);
  }
});

Esistono numerosi avvertenze nel javadoc per il metodo toFront () che potrebbe causare il problema.

Ma ci proverò comunque, quando " solo la scheda nella barra delle applicazioni lampeggia " ;, l'applicazione è stata ridotta a icona? In tal caso, può essere applicata la seguente riga di javadoc:

" Se questa finestra è visibile, porta questa finestra in primo piano e può renderla la finestra focalizzata. "

Per evitare che la finestra si disattivi quando torna a essere visibile dopo essere stato nascosto tutto ciò che serve è:

setExtendedState(JFrame.NORMAL);

In questo modo:

defaultItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                showWindow();
                setExtendedState(JFrame.NORMAL);
            }
});
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top