2 つの非モーダル JDialog を表示した後、JMenuItem アクセラレータが機能しませんか?(マックだけ?)

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

質問

2 つの JDialog を次々に直接表示した後、JMenuItems のアクセラレータが機能しなくなるという問題があります。

問題を再現するこの小さな例を見てください。

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

public class DialogBug
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new StartupRunnable(args.length == 0));
    }

    public static class StartupRunnable
        implements Runnable
    {
        private boolean both;

        public StartupRunnable(boolean both)
        {
            this.both=both;
        }

        public void run()
        {
            MyFrame myFrame=new MyFrame();
            myFrame.setVisible(true);
            myFrame.startUp(both);
        }
    }

    public static class MyFrame
        extends JFrame
    {
        private MyDialog dialog1;
        private MyDialog dialog2;

        public MyFrame()
        {
            super("MyFrame");
            setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            initUI();
        }

        private void initUI()
        {
            dialog1=new MyDialog(this);
            dialog2=new MyDialog(this);
            JMenuBar menuBar=new JMenuBar();
            JMenu fileMenu=new JMenu("File");
            menuBar.add(fileMenu);
            fileMenu.add(new JMenuItem(new OpenAction()));
            setJMenuBar(menuBar);
            setSize(200,200);
        }

        public void startUp(boolean both)
        {
            dialog1.setVisible(true);
            if(both)
            {
                dialog2.setVisible(true);
            }
        }

        private class OpenAction
            extends AbstractAction
        {
            public OpenAction()
            {
                super("Open");
                KeyStroke accelerator = KeyStroke.getKeyStroke("ctrl O");
                putValue(Action.ACCELERATOR_KEY, accelerator);
            }

            public void actionPerformed(ActionEvent e)
            {
                System.out.println("Open executed");
            }
        }

    }

    public static class MyDialog
        extends JDialog
    {
        public MyDialog(JFrame parent)
        {
            super(parent);
            setTitle("Dialog");
            setModal(false);
            add(new JButton(new OkAction()));
            pack();
        }

        private class OkAction
            extends AbstractAction
        {
            public OkAction()
            {
                super("Ok");
            }

            public void actionPerformed(ActionEvent e)
            {
                setVisible(false);
            }
        }
    }
}

を使用してコンパイルします javac DialogBug.java そしてそれを実行して実行します java DialogBug.

「OK」ボタンが 2 つ表示されます。両方のダイアログをクリックして閉じます。ここで「Ctrl-O」を押します。これにより、「オープンが実行されました」とコンソールに出力されるはずですが、これは起こりません。次に、「ファイル」メニューをクリックします。これで、「Ctrl-O」が期待どおりに機能するようになりました。

何らかの引数を指定してアプリを起動すると、 java DialogBug x そうすると、ダイアログが 1 つだけ開き、ダイアログを閉じた直後に「Ctrl-O」が期待どおりに機能します。

私の環境は以下のとおりです。

java version "1.6.0_15"
Java(TM) SE Runtime Environment (build 1.6.0_15-b03-219)
Java HotSpot(TM) 64-Bit Server VM (build 14.1-b02-90, mixed mode)

しかし、私の知る限り、このアプリは他の VM でも同様に動作します。

私を助けてください!
ここで何が問題になるのか全く分かりません。これが Java のバグである場合 (私もそうであると予想しています)、回避策があれば教えてください...

他のシステムでこれを再現できるかできない場合は、コメントでその旨を教えてください。
どうもありがとう!

アップデート
Snow Leopard への Java 1.5 のインストール (はぁ) 少なくとも Snow Leopard では、1.5.0_19 でもこの問題が発生することが確認できました。

アップデート 2
Windows XPで動作します。

java version "1.6.0_13"
Java(TM) SE Runtime Environment (build 1.6.0_13-b03)
Java HotSpot(TM) Client VM (build 11.3-b02, mixed mode, sharing)

java version "1.5.0_13"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_13-b05)
Java HotSpot(TM) Client VM (build 1.5.0_13-b05, mixed mode)

アップデート 3
Windows Vistaでも動作するようです。これは、私の知る限りでは、Mac OS X 10.5+10.6 の問題になります。

アップデート 4
このバグは、Apple で問題 ID #7240026 として報告されています。

役に立ちましたか?

解決

MyDialog クラスの OkAction クラスの actionPerformed メソッドを次のものに置き換えます。

public void actionPerformed(ActionEvent e) {
            setVisible(false);
            MyDialog.this.getParent().requestFocus();
        }

何らかの理由で (おそらくダイアログがモーダルではないため)、OS X はフォーカスを MyFrame に返しません。ダイアログを閉じて消去すると、フォーカスは自然に MyFrame に戻りますが、単にダイアログを非表示にするだけでも何か問題がある可能性があります。

他のヒント

Java(TM) SE ランタイム環境 (ビルド 1.6.0_07-b06) を使用して XP 上で正常に動作します。

どういうわけか、Ctrl+O がコンポーネントの向きを変更するためのアクセラレータであると考えているようです。これがすべてのアクセラレータで発生するのか、それとも Ctrl+O のみで発生するのか気になりますか?

編集:おそらくこの提案は忘れてもよいでしょう。どこでこれを考えたのかを見つけることも思い出すこともできず、テストプログラムでこれを検証することもできません。

OS X 10.4とJavaバージョン「1.5.0_19」を搭載したMacで問題なく実行できました。

2 つのモーダル ダイアログを閉じた後、メイン フレームにフォーカスがあるかどうか疑問に思っています。久しくアクセラレータを使っていなかったのですが、もしかしたらメニューバーに登録されているアクセラレータや、フレーム内に登録されているアクセラレータ(ショートカットのようなもの)に何か変更があったのかもしれないと思います。

頑張ってください。

Leopard/10.5 で試してみましたが、プログラムはどちらでも動作しません。

Java 5 (Apple JVM)

java version "1.5.0_20"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_20-b02-315)
Java HotSpot(TM) Client VM (build 1.5.0_20-141, mixed mode, sharing)

Java 6 (SoyLatte/オープン JDK BSD ポート)

java version "1.6.0_03-p3"
Java(TM) SE Runtime Environment (build 1.6.0_03-p3-landonf_19_aug_2008_14_55-b00)
Java HotSpot(TM) Server VM (build 1.6.0_03-p3-landonf_19_aug_2008_14_55-b00, mixed mode)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top