¿Por qué los botones de radio se representan incorrectamente en un java.awt.Dialog en la Mac cuando el diálogo es modal?

StackOverflow https://stackoverflow.com/questions/1002394

  •  05-07-2019
  •  | 
  •  

Pregunta

Estoy en el proceso de probar mi aplicación Java en la Mac y me he encontrado con un problema muy extraño. Las casillas de verificación que aparecen en un diálogo modal se procesan incorrectamente, aunque los diálogos no modales funcionan bien.

Por ejemplo, digamos que tengo una ventana con 2 botones de opción. Cuando se abre el diálogo se selecciona el primero. Cuando hago clic en el segundo botón, de repente parece que ambos están seleccionados. Al hacer clic en cualquier otro lugar dentro del cuadro de diálogo, la representación se corregirá y solo se mostrará el botón seleccionado.

El siguiente código reproduce esto para mí:

package mactest;

import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Dialog;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class Main {
  public static void main(String[] args) {
    boolean modal = false;
    if(args.length > 0) {
      modal = args[0].toLowerCase().equals("true");
    }

    TestDialog dlg = new TestDialog(new Frame(), modal);

    dlg.setVisible(true);
  }

  private static class TestDialog extends Dialog {
    private Checkbox cb1;
    private Checkbox cb2;

    private CheckboxGroup cbg;

    public TestDialog(Frame owner, boolean modal) {
      super(owner);

      cbg = new CheckboxGroup();

      cb1 = new Checkbox("One", true, cbg);
      cb2 = new Checkbox("Two", false, cbg);

      this.setLayout(new FlowLayout());
      this.add(cb1);
      this.add(cb2);

      this.setModal(modal);
      this.pack();

      this.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e) {
          TestDialog.this.setVisible(false);
          System.exit(0);
        }
      });
    }
  }
}

Si llamo a esto así:

  

java -cp MacTest.jar mactest.Main false

el diálogo no es modal y todo funciona bien. Sin embargo, si le digo que sea modal:

  

java -cp MacTest.jar mactest.Main true

entonces ocurren los problemas de renderizado.

He intentado todos los trucos que se me ocurren para intentar solucionar el problema (invalidar, doLayout, solicitar enfoque, establecer explícitamente el estado de cada botón cuando se selecciona uno, etc.). Pero hasta ahora lo único que hago. He encontrado que las obras son para hacer que el diálogo no sea modal. Desafortunadamente, esa no es una opción en mi aplicación.

En caso de que sea importante, esto es en un MacBook con OS X 10.5 con Java 1.5.0_16.

¿Fue útil?

Solución 2

Encontré algo que parece arreglarlo, aunque es un truco feo. Agregué escuchas de elementos a cada una de las casillas de verificación. Cuando esos disparadores redimensiono la ventana por 1 píxel, luego hago un invokeLater () en pack () (mis cuadros de diálogo no son redimensionables). Aquí está el código de prueba modificado:

package mactest;

import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Dialog;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class Main {
  public static void main(String[] args) {
    boolean modal = false;
    boolean tweak = false;
    if(args.length > 0) {
      modal = args[0].toLowerCase().equals("true");
    }
    if(args.length > 1) {
      tweak = args[1].toLowerCase().equals("true");
    }

    TestDialog dlg = new TestDialog(new Frame(), modal, tweak);

    dlg.setVisible(true);
  }

  private static class TestDialog extends Dialog {
    private Checkbox cb1;
    private Checkbox cb2;

    private CheckboxGroup cbg;

    public TestDialog(Frame owner, boolean modal, boolean tweak) {
      super(owner);

      cbg = new CheckboxGroup();

      cb1 = new Checkbox("One", true, cbg);
      cb2 = new Checkbox("Two", false, cbg);

      this.setLayout(new FlowLayout());
      this.add(cb1);
      this.add(cb2);

      this.setModal(modal);
      this.pack();

      if(tweak) {
        cb1.addItemListener(new ItemListener() {
          public void itemStateChanged(ItemEvent e) {
            onSelection();
          }
        });
        cb2.addItemListener(new ItemListener() {
          public void itemStateChanged(ItemEvent e) {
            onSelection();
          }
        });
      }

      this.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e) {
          TestDialog.this.setVisible(false);
          System.exit(0);
        }
      });
    }

    private void onSelection() {
      Rectangle bounds = this.getBounds();
      this.setBounds(bounds.x, bounds.y, bounds.width + 1, bounds.height);
      EventQueue.invokeLater(new Runnable() {
        public void run() {
          TestDialog.this.pack();
        }
      });
    }
  }
}

Para los componentes redimensionables, necesitarías almacenar el tamaño de ajuste previo y restaurarlos en lugar de llamar al paquete ().

En Windows, podía ver el parpadeo del diálogo de vez en cuando cuando cambiaba la selección, aunque en la Mac no se notaba en absoluto.

Otros consejos

¿Estás preguntando por casillas de verificación o botones de radio? Usted menciona ambos.

Para crear un ámbito de exclusión múltiple, debe utilizar la clase ButtonGroup

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top