javaswingfocusacceleratorkey

Java's setFocusableWindowState and setAccelerator don't play nicely


Under Windows 7 I have a Java program which is started with a window state of JFrame.ICONIFIED and I have a requirement that it doesn't steal the focus when it loads.

I accomplished this by setting setFocusableWindowState to false before calling setVisible and then restoring it back to true afterwards. This works fine and my program loads effectively in the background.

However, I have noticed that none of my keyboard accelerators work anymore and it is a direct result of using setFocusableWindowState. I have even tried setting my keyboard accelerators after the window is visible, but with no luck. The below SSCCE demonstrates the problem - the user isn't able to press CTRL+T if I call setFocusableWindowState.

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

public class SSCCE extends JFrame implements ActionListener {
  private JMenuBar mBar;
  private JMenu mFile;
  private JMenuItem miTest;

  public SSCCE() {
    setSize(300, 200);

    mBar = new JMenuBar();
    mFile = new JMenu("File");
    miTest = new JMenuItem("Test");
    miTest.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
    miTest.addActionListener(this);
    mFile.add(miTest);
    mBar.add(mFile);

    setJMenuBar(mBar);

    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    setExtendedState(getExtendedState() | JFrame.ICONIFIED);
    setFocusableWindowState(false);
    setVisible(true);
    setFocusableWindowState(true);
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    if (e.getSource().equals(miTest)) {
      System.out.println("Testing...");
    }
  }

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        new SSCCE();
      }
    });
  }
}

I am seeing the same behavior on the latest patch release of Java 7 and Java 8. This looks bug like, but open to other suggestions?


Solution

  • I have even tried setting my keyboard accelerators after the window is visible, but with no luck.

    I added the menubar at the end and it works ok for me:

    //setJMenuBar(mBar);
    
    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    setExtendedState(getExtendedState() | JFrame.ICONIFIED);
    setFocusableWindowState(false);
    setVisible(true);
    setFocusableWindowState(true);
    setJMenuBar(mBar);