views:

399

answers:

3

I would like to let my JFrame under Windows not act upon an ALT key press. To clarify, when you execute the following snippet of code:

import javax.swing.*;

public class FrameTest {
    public static void main(String[] args) throws Exception {
        JFrame frame = new JFrame();
        frame.setSize(400, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

and press the ALT key and then the arrow down key, you get a menu in the upper left corner in which you can choose to minimize, move, close etc. the frame (at least I get that). I would like to disable this: ie. the JFrame should not "listen" to these ALT presses.

I believe that certain Windows components react by default on the ALT key because when I add a menu bar to my frame, and explicitly set the look & feel to the system look & feel, the menu (File) is now automatically selected after pressing the ALT key:

import javax.swing.*;

public class FrameTest {
    public static void main(String[] args) throws Exception {
        JFrame frame = new JFrame();
        frame.setSize(400, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("File");
        menuBar.add(menu);
        frame.setJMenuBar(menuBar);
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); // set Windows look and feel
        frame.setVisible(true);
    }
}

and when I remove UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()) from the example above, this behaviour is not exhibited when pressing the ALT key: the menu is not selected, but the JFrame is.

When no look & feel is set, the "Metal" look and feel is used. It is clear by looking at the menu bar in my previous example that you go from "native look" to "Metal look" when you remove UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()) from the code. However, I don't see a change in the JFrame, no matter what look & feel I set, it always looks like a native Windows frame.

So, my question is: how can I disable this ALT behaviour on my JFrame? I guess I can do it by actually changing the look and feel of the JFrame. Is that possible? If so, how?

Thanks!

+1  A: 

It sounds like you're hitting upon some default interactions with the Windows window manager. It is possible that if you draw your own titlebar and borders that Windows will no longer set these default handlers on the Alt key.

You might want to try Substance, which gives you much more control over these sorts of things, while still working with the standard Swing components.

Or, try this before you make your frame visible:

JFrame.setDefaultLookAndFeelDecorated(true);
Adam Goode
I will definitely look at Substance, but that'll be from a personal perspective. I cannot get it in the project: I'll have to find a *Swing solution* or let it be. Thanks for your time, of course!
Bart Kiers
Substance is, at its core, a plugin to Swing. There are more things added on top, but I think you could say it is part of a Swing solution.
Adam Goode
I'll see if I can get a solution with Substance then. If so (and I can't get a Swing-only solution), I'll throw it higher up in the food chain here. Thanks again Adam.
Bart Kiers
See my edit: try `JFrame.setDefaultLookAndFeelDecorated(true);` or the like.
Adam Goode
Thanks Adam, already tried it without success.
Bart Kiers
Hmm, I suspect Substance won't work either, then.
Adam Goode
+1  A: 

Actually, what you are seeing here is pretty much outside your nice, Swing-y Java world. The window frame (except for MDI interfaces) will always be drawn by the window manager of the underlying operating system. And that's also the reason why the Alt key behaves like you observe. This key is intercepted by the WM in this case and it decides that you want to bring up the system menu of the program. That's totally unrelated to Java.

For several reasons you can't change the "look and feel" of the window frame, the main one being that this is outside Swing's PLAF system. You can remove the window frame, leaving behind a naked window (freezing in the cold November wind), then you also shouldn't get a system menu anymore.

Furthermore you could try handling the Alt keypress and not delegating that very keypress further (the application gets it before the WM does, so you can mess with these things). My Java-Fu is a little rusty right now, though, so no idea if and how this can be achieved.

Joey
Thanks for your response Johannes. I was afraid of that.
Bart Kiers
+1  A: 

Just for history:

You can do this. Window manger handles all the events to the current keyboard focus manager and it decides what to do with the particular key. Every swing application has only one keyboard focus manager that's why your changes will affect the whole application and not the particular frame. The code below should do the trick:

frame.addFocusListener(new FocusListener() {
        private final KeyEventDispatcher altDisabler = new KeyEventDispatcher() {
            @Override
            public boolean dispatchKeyEvent(KeyEvent e) {
                return e.getKeyCode() == 18;
            }
        };

        @Override
        public void focusGained(FocusEvent e) {
            KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(altDisabler);
        }

        @Override
        public void focusLost(FocusEvent e) {
            KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(altDisabler);
        }
    });
Alex Nikolaenkov
Thanks for the info Alex.
Bart Kiers