2014-06-23 16 views
8

Sto provando a creare un tipo di barra degli strumenti in un frame alwaysOnTop non decorato. Quindi, voglio che il mio frame sia sopra il mio frame principale, ma non sopra i frame di altri programmi. Ho provato questo codice:Frame sempre sopra il mio programma solo

public class Test { 
    private static JFrame mainFrame; 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       mainFrame = new JFrame("test"); 
       mainFrame.setSize(800,600); 
       mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       mainFrame.setVisible(true); 

       A a = new A(); 
      } 
     }); 
    } 

    public static class A extends JDialog { 

     public A() { 
      super(mainFrame); 
      setAlwaysOnTop(true); 
      setFocusable(false); 
      setSize(80,60); 
      setVisible(true); 
     } 
    } 
} 

Ma nonostante l'uso di JDialog e precisando il proprietario, il soggiorno cornice in cima ad altre applicazioni (almeno con Ubuntu Forse il risultato è differente con l'altro sistema operativo.?)

EDIT: Ok, ho provato questo codice per il mio dialogo:

public static class A extends JDialog { 

    public A(String name) { 
     super(mainFrame, name); 
     setAlwaysOnTop(true); 
     setFocusable(false); 
     setSize(80, 60); 
     setVisible(true); 

     mainFrame.addWindowListener(new WindowAdapter() { 
      @Override 
      public void windowActivated(WindowEvent e) { 
       A.this.setAlwaysOnTop(true); 
      } 

      @Override 
      public void windowDeactivated(WindowEvent e) { 
       // A.this.setAlwaysOnTop(false); 
       A.this.toBack(); 
      } 
     }); 
    } 
} 

il problema ora è che quando la finestra principale di messa a fuoco sciolti, la finestra di dialogo ruba la messa a fuoco posteriore e non capisco perché. Ad esempio, eseguo la mia app, provo a passare a Firefox, compare Firefox e copre MainFrame, ma la finestra di dialogo A diventa attiva e rimane sullo schermo. Ora, se seleziono di nuovo Firefox, alla fine la finestra di dialogo scomparirà correttamente. Potresti spiegarmi perché il dialogo ha il focus?

Grazie

+0

Penso che è necessario ricorrere all'utilizzo di un qualche tipo di hack nativa tramite JNI/JNA – MadProgrammer

+0

'classe A estende JFrame'? –

+0

cosa succede se rimuovi 'setAlwaysOnTop()'? Normalmente, Frame dovrebbe rimanere sopra altri frame. Il 'setAlwaysOnTop()' sta impostando un flag per l'OS – GameDroids

risposta

4

Ok, ho trovato una soluzione (non so se è la soluzione, ma che sta funzionando, quindi ...)

ho scoperto setFocusableWindowState(), che è perfetto per le barre degli strumenti. A proposito, non so se il mio precedente setFocusable (falso) abbia avuto alcun effetto.

Il problema successivo è stato che l'attenzione diventa comportamento molto strano con questo codice: se posso passare da MyApp a Firefox, ecco cosa succede:

focus : MyApp -> Firefox 
execution of MyDialog.toFront() 
focus : Firefox -> MyDialog 
MyDialog not focusable ! 
focus : MyDialog -> MyApp !!! 

risultato: nulla è cambiato!

Quindi ho finalmente ottenuto i trucchi: subito dopo MyDialog.toFront(), si restituisce l'attivo al proprietario precedente. E l'unico modo che ho trovato per fare questo con nessun errore era: mainFrame.toBack()

codice finale:

public class Test { 
    private static JFrame mainFrame; 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       mainFrame = new JFrame("test"); 
       mainFrame.setSize(800,600); 
       mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       mainFrame.setVisible(true); 

       A a = new A(); 
      } 
     }); 
    } 

    public static class A extends JDialog { 

     public A() { 
      super(mainFrame); 
      setAlwaysOnTop(true); 
      setFocusableWindowState(false); 
      setSize(80,60); 
      setVisible(true); 

      mainFrame.addWindowListener(new WindowAdapter() { 
       @Override 
       public void windowActivated(WindowEvent e) {A.this.setAlwaysOnTop(true);} 
       @Override 
       public void windowDeactivated(WindowEvent e) { 
        A.this.toBack(); 
        mainFrame.toBack(); 
       } 
      }); 
     } 
    } 
} 
+0

Ho confermato questa soluzione in Windows 10. Grazie –

4

si dovrebbe fare la vostra finestra sempre in primo piano solo quando la finestra padre va attivata. Qualcosa di simile a questo:

public class Test { 
    private static JFrame mainFrame; 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       mainFrame = new JFrame("test"); 
       mainFrame.setSize(800,600); 
       mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       mainFrame.setVisible(true); 

       final A a = new A(); 
       mainFrame.addWindowListener(new WindowAdapter() { 
        /** 
        * {@inheritDoc} 
        */ 
        @Override 
        public void windowDeactivated(WindowEvent e) { 
         a.setAlwaysOnTop(false); 
        } 

        /** 
        * {@inheritDoc} 
        */ 
        @Override 
        public void windowActivated(WindowEvent e) { 
         a.setAlwaysOnTop(true); 
        } 
       }); 
      } 
     }); 
    } 

    public static class A extends JDialog { 

     public A() { 
      super(mainFrame); 
      setAlwaysOnTop(true); 
      setFocusable(false); 
      setSize(80,60); 
      setVisible(true); 
     } 
    } 
} 
+0

Suona bene. Proviamo nel mio vero programma. Ti farò sapere. – Sharcoux

+0

Ok. Ho provato il tuo approccio. non funziona con setAlwaysOnTop (false), ma con toBack(). Tuttavia, ho ancora un piccolo problema. Per favore, vedi la mia modifica. E grazie per il tuo aiuto! – Sharcoux

+0

@ user1967800 quando il frame è in alto ruba la messa a fuoco. Quindi devi impostare alwaysOnTop su false. –

Problemi correlati