How to globally change the ActionMap of Swing JTex

2019-07-21 06:51发布

问题:

I want to change the ActionMap of Swing JTextFields in my entire Application by replacing a few actions by my custom implmentations. For an explanation why you can refer to the following post:

How do I make the caret of a JTextComponent skip selected text?

This works well if I do this:

ActionMap map = (ActionMap)UIManager.get("TextField.actionMap");
map.put(DefaultEditorKit.backwardAction, new MyCustomAction());

The only remaining problem now is that so far I have only gotten this to work, when I execute that code after the first instantiation of a JTextField. However, ideally I would like to integrate this code in a custom look and feel or some other central place that does not have to know about the application. Calling

UIManager.getDefaults()

first does not change anything. The map returned by UIManager.get("TextField.actionMap") is still null afterwards.

Right now I am Stuck with putting a dummy new JTextField() in some initialization method of my application and then manipulate the action map which is very ugly.

回答1:

The shared parent actionMap is created at the moment when the first instance of a XXTextComponent gets its uidelegate. The method is in BasicTextUI:

/**
 * Fetch an action map to use.
 */
ActionMap getActionMap() {
    String mapName = getPropertyPrefix() + ".actionMap";
    ActionMap map = (ActionMap)UIManager.get(mapName);

    // JW: we are the first in this LAF
    if (map == null) {
        // JW: create map
        map = createActionMap();
        if (map != null) {
            // JW: store in LAF defaults
            UIManager.getLookAndFeelDefaults().put(mapName, map);
        }
    }
    ....
}

So if you want to add to that map, you have to do so after setting a LAF and after creating an instance.

There's no way around, even though it feels ugly.