2012-09-05 19 views
8

Ho convalidato un'applicazione swing che viene eseguita su un'applet per mac osx.Problemi di messa a fuoco con le finestre di dialogo modale java7 su mac osx

Durante questa convalida ho trovato i seguenti problemi con le finestre di dialogo modali:

  1. Quando una finestra di dialogo è aperta ed è setModal (true) blocca il contenuto della finestra principale, ma se si fa clic da qualche parte sulla finestra di root, la finestra di dialogo va sotto, ma dovrebbe rimanere nella parte superiore della finestra di root.
  2. Se la finestra di dialogo ha un JTextInputField, non riceve l'attivazione anche quando si fa clic su di esso.

Così ho creato un piccolo programma per mostrare il problema. Potete per favore aiutarmi a capire cosa c'è di sbagliato qui?

package com.macosx.tests; 

import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 

public class DialogExample extends JApplet{ 

    private static final long serialVersionUID = 1L; 
    private JPanel panel; 
    private JButton openDialogBtn; 

    private void doStart() { 
     panel = new JPanel(); 
     panel.setPreferredSize(new Dimension(500,500)); 

     openDialogBtn = new JButton("open dialog"); 
     openDialogBtn.addActionListener(new ActionListener(){ 

      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       ModalDialog dialog = new ModalDialog(panel, true); 
       dialog.setVisible(true); 
      } 

     }); 
     panel.add(openDialogBtn); 
     setContentPane(panel); 
    } 


    class ModalDialog extends JDialog { 
     private static final long serialVersionUID = 1L; 

     public ModalDialog(Component parent, boolean modal) { 
      Dimension dimensionParentFrame = parent.getSize(); 
      setSize(new Dimension((parent == null) ? 300 : dimensionParentFrame.width/2, 75)); 

      setModal(modal); 
      setModalityType(ModalityType.APPLICATION_MODAL); 

      JTextField txtField = new JTextField(); 
      add(txtField, BorderLayout.CENTER); 
     } 
    } 


    @Override 
    public void start() { 
     try { 
      SwingUtilities.invokeAndWait(new Runnable() { 
       public void run() { 
        doStart(); 
       } 
      }); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

} 

Utilizzare quanto sopra per creare un file .jar (test.jar). Una volta fatto ciò, creare un file html con il seguente contenuto:

<html> 
<head> 
<title>Dialog test Applet</title> 
</head> 
<body> 
<applet id="DialogTestApplet" height="800" width="600" 
    code="com.macosx.tests.DialogExample" 
    archive="test.jar"> 
</applet> 
</div> 
</body> 
</html> 

Quando questo è fatto, eseguire il file html. Vedrai un'applet con uno sfondo grigio e con un pulsante. Quindi provare a:

  1. fare clic sul pulsante per aprire la finestra di dialogo. Successivamente, fai clic in qualche punto nell'area grigia: la finestra di dialogo va sotto la finestra del browser ma dovrebbe rimanere in alto, giusto?
  2. fare clic sul pulsante per aprire la finestra di dialogo. Dopo di che fai clic sul campo di testo della finestra di dialogo e prova a scrivere qualcosa: la finestra di testo non riceve il focus.

Quindi, cosa sto facendo di sbagliato qui? Qualcuno con un computer Mac può testare questo per favore?

Grazie

Spec:

java.vendor Oracle Corporation 
java.version 1.7.0_07 
os.name  Mac OS X 
os.version  10.7.4 

browser  firefox 15 

NOTA: si prega di notare che questa è solo accadendo quando l'applet viene eseguito sul browser e solo su Mac OSX.

+0

Impossibile riprodurre su 10.5/1.6. – trashgod

+0

Per me, usando 10.7/1.6.0_33 vedo ancora il problema modale (1) ma non il problema di messa a fuoco (2). –

+0

Problema simile ma su ubuntu [stackoverflow] (http://stackoverflow.com/questions/12373140/java-applet-jtextfield-inaccesible-after-jdialog-on-ubuntu). – user1307657

risposta

1

Si dovrebbe mettere una finestra "proprietario" sul proprio ModalDialog. Per fare ciò, è necessario chiamare super (proprietario) nel costruttore ModalDialog e recuperare la finestra principale del componente parent con SwingUtilities.getWindowAncestor(parent).

+0

Grazie per il tuo suggerimento. Ho appena provato quello che hai menzionato, ma il risultato è stato lo stesso ... –

+0

@ LuisGonçalves prova a pubblicare un [SSCCE] (http://sscce.org) senza dover usare un'applet. –

+0

perché non basta copiare quel codice su Eclipse, per esempio, e selezionare Esegui come -> Applet Java. Questo eseguirà l'applet e lo vedrai in esecuzione. Ma come ho detto nella nota: questo problema si verifica solo quando eseguiamo l'applet sul browser che è esattamente come sono interessato a farlo funzionare. –

1
  • non Mac/OSX utente ma questo è problema comune su Focus e JDialog,

  • ci sono altri problemi nel caso in cui JDialog è creato su Runtime,

  • Focus è asincrona Based su proprietà è venuto da Native OS

  • creare questo JDialog una sola volta e re_use questo container per un'altra azione

  • JDialog#setVisible devono essere imballati in invokeLater() troppo

  • è possibile forzare la Focus da JTextField#setText(JTextField#getText()) avvolto in invokeLater()

  • c'è Dialog Focus, di grande soluzione da @camickr

+0

Farò alcune modifiche al codice per includere i suggerimenti dei dos per vedere se qualcuno di loro risolve i problemi. Solo per dire che se si esegue lo stesso codice su Windows, nessuno dei problemi si verifica. –

+0

@Luis Gonçalves questo problema comune è presentato nella GUI più complessa su piattaforme Win, ** nix e OSX, solo gli hack possono aiutarti – mKorbel

+0

L'hai effettivamente eseguito su Windows ?! Perché, non vedo nessuno dei problemi se lo eseguo sul mio computer Windows ... –

1

I conferma, ho lo stesso bug con una vecchia applet in esecuzione su JDK7 su OS X. Come menzionato nel poster, il bug è visto solo con l'applet in esecuzione nel browser (ff) e non con l'appletviewer.

+0

Grazie per la segnalazione. A proposito, puoi dare un'occhiata in http://stackoverflow.com/questions/12180557/swing-menus-java-7-mac-osx. Ho anche creato quello che sembra un bug. Lo confermi? –

1

Posso verificare che questo sia un problema per Java 1.7 Update 7+ su Safari 6 e Firefox in esecuzione su Mountain Lion. Curiosamente, non è un problema nelle versioni precedenti di Safari eseguite su Lion, ma si tratta di un problema in Firefox sul vecchio sistema operativo. Sono piuttosto disperato di trovare una soluzione per questo come un numero di miei utenti di applet sono su Mac. Una soluzione alternativa che ho trovato (che non è sufficiente in alcun modo) è quella di minimizzare la finestra e quindi riaprirla. I campi di testo/textareas diventano quindi modificabili. Speriamo di trovare una soluzione migliore per aggirare questo fastidioso requisito.

1

Ho riscontrato lo stesso problema su Mac con Java 7 update 9 con Safari e Firefox. Quando ho aperto un JDialog che conteneva un JTextField, il JTextField non era accessibile.

Ho trovato una soluzione. Ho inserito un ritardo da quando l'utente ha premuto il pulsante "Mostra finestra di dialogo" per eseguire il codice che mostra il pulsante.

Ad esempio:

ActionListener al = new ActionListener(){ 
    public void actionPerformed(ActionEvent ae){ 
     TitleDialog dialog = new TitleDialog(main.findParentFrame()); // My JDialog which contains a JTextField. 
     dialog.setVisible(true); 
    } 
}; 
javax.swing.Timer timer = new javax.swing.Timer(1000, al); 
timer.setRepeats(false); 
timer.start(); 

ho sperimentato che se il ritardo è stato quello di breve la soluzione non avrebbe funzionato.

Se si utilizza SwingUtilities.invokeLater anziché javax.swing.Timer, non funzionerà. Forse il ritardo di SwingUtilities.invokeLater è troppo breve.

+0

questo non ha funzionato per me quindi state attenti con questa soluzione –

6

Ho trovato un'altra soluzione. Quando la finestra è aperta, mostra un'opzione per alcuni millisecondi e chiudila. Dà il focus sull'opzione e poi torna alla finestra di dialogo, permettendo di ignorare il bug.

Aggiungere questo snipet di codice al costruttore di dialogo e dovrebbe funzionare:

addWindowListener(new WindowAdapter(){ 
public void windowOpened(WindowEvent e){ 
    JOptionPane pane = new JOptionPane(); 
    final JDialog dialog = pane.createDialog("Please Wait"); 
    Timer timer = new Timer(50, new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      dialog.dispose(); 
     } 
    }); 
timer.setRepeats(false); 
timer.start(); 
dialog.setVisible(true); 
} 
+1

Potete provare la finestra di dialogo invisibile: 'dialog JDialog finale = new JDialog(); dialog.setDefaultCloseOperation (JDialog.DO_NOTHING_ON_CLOSE); dialog.setUndecorated (true); dialog.setModal (true); ' – xmedeko

0

voglio utilizzare la soluzione precedente (alla finestra dalla finestra di dialogo Apri), ma senza mostrare alcun dialogo. Ecco un codice per la finestra di dialogo non visibile.

final JDialog dialog = new JDialog(); 
dialog.setUndecorated(true); 
dialog.setSize(0, 0); 
dialog.setModal(true); 
dialog.pack(); 
Problemi correlati