1

メニューを有効または無効にするJavaプログラムがあります。Windowsでも問題なく動作しますが、Macで実行すると問題が発生します。

問題を示すコードを次に示します。

import javax.swing.*;
import java.awt.event.*;

public class PopTest extends JFrame {
    JMenu menu1;
    JMenu menu2;

    public PopTest() {
        menu1 = new JMenu("Menu 1");
        menu2 = new JMenu("Menu 2");
        menu2.setEnabled(false);

        menu1.add(new JMenuItem(new AbstractAction("With popup") {
                public void actionPerformed(ActionEvent event) {
                    JOptionPane.showMessageDialog(PopTest.this,"Popup","Popup",JOptionPane.ERROR_MESSAGE);
                    menu2.setEnabled(true);
                    menu2.add(new JMenuItem("New item"));
                }
            }));

        menu1.add(new JMenuItem(new AbstractAction("Without popup") {
                public void actionPerformed(ActionEvent event) {
                    menu2.setEnabled(true);
                    menu2.add(new JMenuItem("New item"));
                }
            }));

        JMenuBar menuBar = new JMenuBar();
        menuBar.add(menu1);
        menuBar.add(menu2);
        setJMenuBar(menuBar);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(200, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        try {
            System.setProperty("apple.laf.useScreenMenuBar", "true");
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch(Exception e) {
            System.out.println("Exception: " + e.getMessage());
        }

        SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new PopTest();
                }
            });

    }
}

これはプログラムが行うことです:

プログラムには、「メニュー1」と「メニュー2」の2つのメニューがあります。最初から、メニュー1は有効で、メニュー2は無効です。

メニュー1には、ほぼ同じことを行う2つの項目があります。メニュー2を有効にし、メニュー項目を追加します。違いは、メニュー2を有効にする前に、一方の項目がメッセージダイアログを表示するのに対し、もう一方の項目は表示しないことです。

次に、プログラムをコンパイルして、これを試してください。

実験1:メニュー1>ポップアップなしを選択します。次にメニュー2をクリックすると、メニューに「新規アイテム」と呼ばれる有効なメニューアイテムがあることがわかります。

実験2:プログラムを閉じます!プログラムを再起動してください。メニュー1>ポップアップ付きを選択します。メッセージダイアログで[OK]をクリックします。メニュー2をクリックすると、メニューに「新規アイテム」と呼ばれる無効なメニューアイテムがあることがわかります。デスクトップ上の他の場所をクリックして、アプリケーションがフォーカスを失うようにします。アプリケーションをクリックします。メニュー2をクリックすると、メニュー項目が有効になっていることがわかります。

実験2では、デスクトップ上の他の場所をクリックするように指示される前に、アプリケーションがフォーカスを失わないことが非常に重要です。そうしないと、問題は発生しません。

2番目の実験でメニュー2のメニュー項目が無効になっているのはなぜですか?これはバグですか?OS X 10.8.2(Mountain Lion)とJava1.7.0_09を使用しています。

4

2 に答える 2

2

この問題はJava7で再現できますが、Java 6では再現できません。なぜこれが行われるのかわかりませんが、問題を修正した1つの方法は、setEnabled()をJOptionPane.showMessageDialog()の上に移動することでした。

    menu1.add(new JMenuItem(new AbstractAction("With popup")
    {
        public void actionPerformed(ActionEvent event)
        {
            menu2.setEnabled(true);
            JOptionPane.showMessageDialog(Test.this, "Popup", "Popup", JOptionPane.ERROR_MESSAGE);
            menu2.add(new JMenuItem("New item"));
        }
    }));
于 2012-11-02T21:06:15.013 に答える
1

以前のバージョンでは、両方のメニューが常に有効になっていますが、に1秒Runnableを投稿することで、特定のシーケンスを適用できますEventQueue

EventQueue.invokeLater(new Runnable() {

    @Override
    public void run() {
        menu2.add(new JMenuItem("New item"));
    }
});

テストされたように; デフォルトのL&F、@Override注釈、および使用法に注意してpack()ください。

import java.awt.EventQueue;
import java.awt.event.*;
import javax.swing.*;

public class PopTest extends JFrame {

    JMenu menu1;
    JMenu menu2;

    public PopTest() {
        menu1 = new JMenu("Menu 1");
        menu2 = new JMenu("Menu 2");
        menu2.setEnabled(false);

        menu1.add(new JMenuItem(new AbstractAction("With popup") {

            @Override
            public void actionPerformed(ActionEvent event) {
                JOptionPane.showMessageDialog(PopTest.this,
                    "Popup", "Popup", JOptionPane.ERROR_MESSAGE);
                menu2.setEnabled(true);
                menu2.add(new JMenuItem("New item"));
            }
        }));

        menu1.add(new JMenuItem(new AbstractAction("Without popup") {

            @Override
            public void actionPerformed(ActionEvent event) {
                menu2.setEnabled(true);
                EventQueue.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        menu2.add(new JMenuItem("New item"));
                    }
                });
            }
        }));

        JMenuBar menuBar = new JMenuBar();
        menuBar.add(menu1);
        menuBar.add(menu2);
        setJMenuBar(menuBar);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setSize(200, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        System.setProperty("apple.laf.useScreenMenuBar", "true");

        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new PopTest();
            }
        });

    }
}
于 2012-11-02T17:41:29.430 に答える