2012-09-05 15 views
8

He estado validando una aplicación swing que se ejecuta en un applet para mac osx.Problemas de foco con los diálogos modales java7 en mac osx

Durante esta validación He encontrado los siguientes problemas con los cuadros de diálogo modales:

  1. Cuando un cuadro de diálogo está abierto y es setModal (verdadero) que bloquea el contenido de la ventana raíz, pero si hace clic en algún lugar de la ventana raíz, el cuadro de diálogo va debajo de ella, pero debe permanecer en la parte superior de la ventana raíz.
  2. Si el cuadro de diálogo tiene un JTextInputField, no recibe el foco incluso cuando hace clic en él.

Así que creé un pequeño programa para mostrar el problema. ¿Puedes ayudarme a entender qué está mal aquí?

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

} 

Utilice lo anterior para crear un archivo .jar (test.jar). Una vez hecho esto, crear un archivo HTML con el siguiente contenido:

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

Cuando se hace esto, ejecute el archivo html. Verá un applet con un fondo gris y con un botón. Luego intente:

  1. haga clic en el botón para abrir el cuadro de diálogo. Después de eso, haga clic en algún lugar del área gris: el cuadro de diálogo se encuentra debajo de la ventana del navegador, pero debe permanecer en la parte superior, ¿no?
  2. haga clic en el botón para abrir el cuadro de diálogo. Después de eso, haga clic en el campo de texto del cuadro de diálogo e intente escribir algo: el texto del diálogo no recibe el foco.

Entonces, ¿qué estoy haciendo mal aquí? ¿Alguien con una computadora Mac puede probar esto por favor?

Gracias

Especificaciones:

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

browser  firefox 15 

NOTA: tenga en cuenta que esto sólo ocurre cuando el applet se ejecuta en el navegador y sólo en Mac OSX.

+0

No se pudo reproducir en 10.5/1.6. – trashgod

+0

Para mí, usando 10.7/1.6.0_33 Todavía veo el problema modal (1) pero no el problema de enfoque (2). –

+0

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

Respuesta

1

Debe poner una ventana de "propietario" en su ModalDialog. Para hacerlo, debe llamar a super (owner) en su constructor ModalDialog y puede recuperar la ventana primaria de su componente parent con SwingUtilities.getWindowAncestor(parent).

+0

Gracias por su sugerencia. Probé lo que mencionaste pero el resultado fue el mismo ... –

+0

@ LuisGonçalves intenta publicar un [SSCCE] (http://sscce.org) sin tener que usar un applet. –

+0

por qué no solo copia ese código a Eclipse, por ejemplo, y selecciona Ejecutar como -> Applet de Java. Eso ejecutará el applet y lo verá funcionando. Pero como mencioné en la nota: este problema solo ocurre cuando ejecutamos el applet en el navegador, que es exactamente lo que me interesa hacer que funcione. –

1
  • no usuario de Mac/OS X, pero esto es tema común acerca Focus y JDialog,

  • hay otros problemas en el caso de que JDialog se crea en tiempo de ejecución,

  • Focus es asincrónica basada en propiedades vino de Native OS

  • crear este JDialog solo una vez y re_use este container para otra acción

  • JDialog#setVisible debe ser envuelto en invokeLater() demasiado

  • es posible forzar el Focus por JTextField#setText(JTextField#getText()) envuelto en invokeLater()

  • hay Dialog Focus, uno de gran solución por @camickr

+0

Voy a hacer algunos cambios de código para incluir dos sugerencias para ver si alguno de ellos resuelve los problemas. Solo mencionar que si ejecuta el mismo código en Windows, ninguno de los problemas ocurre. –

+0

@Luis Gonçalves este problema común se presenta en la GUI más compleja en las plataformas Win, ** nix y OSX, solo los hacks pueden ayudarlo – mKorbel

+0

¿Realmente ejecutó eso en Windows? Porque, no veo ninguno de los problemas si lo ejecuto en mi máquina de Windows ... –

1

I Confirmo, tengo el mismo error con un viejo applet que se ejecuta en JDK7 en OS X. Como mencionó el póster, el error se ve solo con el applet ejecutándose en el navegador (ff) y no con el appletviewer.

+0

Gracias por informar que. Por cierto, ¿puedes echarle un vistazo en http://stackoverflow.com/questions/12180557/swing-menus-java-7-mac-osx. También creé ese que parece un error. ¿Confirmas eso? –

1

Puedo verificar que esto es un problema para Java 1.7 Update 7+ en Safari 6 y Firefox corriendo en Mountain Lion. Curiosamente, no es un problema en las versiones anteriores de Safari que se ejecutan en Lion, pero es un problema en Firefox en el sistema operativo anterior. Estoy bastante desesperado por encontrar una solución para esto ya que varios de mis usuarios de applet están en Mac. Una solución que he encontrado (que no es suficiente de ninguna manera) es minimizar la ventana y luego volver a abrirla. Los campos de texto/áreas de texto se vuelven editables. Con suerte, podemos encontrar una solución mejor que solucione este requisito molesto.

1

Tuve el mismo problema en Mac con Java 7 update 9 con Safari y Firefox. Cuando abrí un JDialog que contenía un JTextField, el JTextField era inaccesible.

Encontré una solución. Inserté un retraso desde que el usuario presionó el botón "mostrar diálogo" hasta ejecutar el código que muestra el botón.

Por ejemplo:

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

que experimentaron que si el retraso se corta a la solución no funcionaría.

Si se utiliza SwingUtilities.invokeLater en lugar de javax.swing.Timer, no funcionará. Tal vez el retraso de SwingUtilities.invokeLater es demasiado corto.

+0

esto no funcionó para mí, así que tenga cuidado con esta solución –

6

Encontré otra solución. Cuando se abre la ventana, muestre un panel de opción durante unos milisegundos y ciérrelo. Da el foco al panel de opciones y luego vuelve al diálogo, lo que permite ignorar el error.

Añadir esta snipet de código a su constructor de diálogo y debería funcionar:

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

Puede intentar el diálogo invisible: 'diálogo JDialog final = nuevo JDialog(); dialog.setDefaultCloseOperation (JDialog.DO_NOTHING_ON_CLOSE); dialog.setUndecorated (true); dialog.setModal (true); ' – xmedeko

0

Quiero usar la solución anterior (para abrir el diálogo desde el diálogo), pero sin mostrar ningún cuadro de diálogo. Aquí hay un código para el diálogo no visible.

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