views:

371

answers:

4

I have the problem that the accelerators of JMenuItems aren't working anymore after showing two JDialogs directly after one another.

Please take a look at this small example that reproduces the problem:

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

Compile it using javac DialogBug.java and execute it running java DialogBug.

You'll see two with "Ok"-Buttons. Dismiss both dialogs clicking them. Now press "Ctrl-O". This should print "Open executed" to the console but this won't happen. Now click the "File" menu. Now "Ctrl-O" will work as expected.

If you start the app with any argument, e.g. java DialogBug x then only one dialog will open and "Ctrl-O" will work immediately after dismissing the dialog, as expected.

My environment is the following:

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)

But as far as I know this app behaves similar in other VMs.

Please help me!
I really don't have any idea what might go wrong here. If this is a Java bug (and I expect it to be one) then please let me know if you have a workaround...

If you can or can't reproduce this on other systems please tell me so in the comments.
Thanks a lot!

Update
After installing Java 1.5 on Snow Leopard (sigh) I can confirm that this happens with 1.5.0_19, too, at least on Snow Leopard.

Update 2
Works for me on 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)

Update 3
Seems to work on Windows Vista, too. This makes this a Mac OS X 10.5+10.6 issue, AFAIK so far.

Update 4
This bug is filed under Problem ID #7240026 at Apple.

A: 

Works fine for me on XP using Java(TM) SE Runtime Environment (build 1.6.0_07-b06).

For some reason I seem to think that Ctrl+O is the accelerator for changing a components orientation. Just wondering if this happens with all accelerators or only Ctrl+O?

Edit: you can probably forget this suggestion. I can't seem to find/recall where I may have thought this and and can't verify this in any of my test programs.

camickr
(You know you need to be running JRE 1.6.0 with at least update 6u15 or 6u16 to have all the latest security patches?)
Tom Hawtin - tackline
I don't do any real work with it, I just use it to play around.
camickr
"Ctrl-O" is just an arbitrary example. No accelerators are working at all.
Huxi
A: 

I ran it without problem on my mac that has OS X 10.4 and Java version "1.5.0_19".

I'm wondering if after you close the two modal dialogs the main frame has the focus. I have not used accelerators in a long while, but I think that maybe there has been some recent change regarding accelerators registered in the menu bar, and accelerators registered in the frame (like shortcuts).

Good luck with it.

nozebacle
Thanks. This is getting stranger and stranger. It misbehaves like described on Leopard, too. I believe that it shows the same malfunction on Windows Vista but I'm waiting for a confirmation...
Huxi
Nope, it seems to work on Vista, too.
Huxi
A: 

I've tried on Leopard/10.5 and the program does not work with either:

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/Open JDK BSD Port)

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)
Rob Smith
+1  A: 

Replace the actionPerformed method of the OkAction class in the MyDialog class with the following:

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

For some reason (maybe because the dialogs aren't modal), OS X is not returning the focus to your MyFrame. The focus returns to MyFrame naturally if you dismiss the dialogs by closing them, but there might be something with simply hiding the dialogs.

GalaJon
Thanks a lot!! This works!
Huxi