0

我正在 Mac 上测试我的 Java 应用程序,但遇到了一个非常奇怪的问题。出现在模态对话框中的复选框呈现不正确,但非模态对话框工作正常。

例如,假设我有一个带有 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、请求焦点、在选择一个按钮时显式设置每个按钮的状态等)。但到目前为止,我唯一要做的就是完成这项工作是使对话框不是模态的。不幸的是,这不是我的应用程序中的一个选项。

万一这很重要,这是在运行 Java 1.5.0_16 的运行 OS X 10.5 的 MacBook 上。

4

2 回答 2

0

I found something that seems to fix it, though it's an ugly hack. I added item listeners to each of the Checkboxes. When those trigger I resize the window by 1 pixel, then do an invokeLater() on pack() (my dialogs aren't resizable). Here's the modified test code:

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

For resizable components you'd need to store the size pre-tweak and restore that instead of calling pack().

In windows I could see the dialog flicker every once in a while when I changed the selection, though on the mac it wasn't noticeable at all.

于 2009-06-18T20:20:55.987 回答
0

你问的是复选框还是单选按钮?你提到两者。

要创建多重排除范围,您必须使用 ButtonGroup 类

于 2009-06-16T16:20:14.927 回答