Почему переключатели неправильно отображаются в java.awt.Dialog на Mac, когда диалог модальный?

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

  •  05-07-2019
  •  | 
  •  

Вопрос

Я тестирую свое Java-приложение на Mac и столкнулся с очень странной проблемой. Флажки, которые появляются в модальном диалоге, отображаются неправильно, хотя немодальные диалоги работают нормально.

Например, скажем, у меня есть окно с 2 переключателями. Когда открывается диалоговое окно, выбирается первый. Когда я нажимаю на вторую кнопку, она внезапно выглядит так, как будто выбраны оба. Если щелкнуть мышью в любом другом месте диалогового окна, рендеринг будет исправлен, и будет отображаться только выбранная кнопка.

Следующий код воспроизводит это для меня:

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

Если я назову это так:

  

java -cp MacTest.jar mactest.Main false

диалог не модальный и все работает нормально. Однако, если я скажу, что это модально:

  

java -cp MacTest.jar mactest.Main true

тогда возникают проблемы с рендерингом.

Я испробовал все уловки, которые только мог придумать, чтобы попытаться исправить проблему (сделать недействительными, doLayout, запрос фокуса, явную настройку состояния каждой кнопки, когда она выбрана и т. д.), но пока единственное, что я Я пришел к выводу, что это делает диалог не модальным. К сожалению, это не вариант в моем приложении.

Если это имеет значение, это на MacBook под управлением OS X 10.5 с Java 1.5.0_16.

Это было полезно?

Решение 2

Я нашел кое-что, что, кажется, исправило бы это, хотя это - уродливый взлом. Я добавил слушателей элемента для каждого из флажков. Когда они срабатывают, я изменяю размер окна на 1 пиксель, затем выполняю invokeLater () для pack () (мои диалоговые окна не меняются). Вот модифицированный тестовый код:

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

Для компонентов с изменяемым размером вам нужно сохранить предварительную настройку размера и восстановить ее вместо вызова pack ().

В окнах я иногда видел, как диалоговое окно мерцало, когда я менял выделение, хотя на Mac это было совсем не заметно.

Другие советы

Вы спрашиваете о флажках или радиокнопках? Вы упоминаете оба.

Чтобы создать область множественного исключения, вы должны использовать класс ButtonGroup

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top