4

我正在尝试使用 UIManager 来获取和清除一些默认键绑定,以便空格键不会激活我的 JButton,如此所述。问题是,可能由于我的合成器外观和感觉,(InputMap)UIManager.get("Button.focusInputMap");返回一个null. 有谁知道以其他方式轻松清除组件输入映射的方法,或者为什么 UIManager 在这种情况下返回 null ?任何提示表示赞赏,在此先感谢。

4

2 回答 2

4

首先:我喜欢 @David 在另一个答案中建议的装饰 StyleFactory 的想法 :-) - 所以如果可行的话,建议使用这个方向。

无论如何,忍不住尝试一下:看起来 Nimbus(可能还有其他基于 Synth 的 LAF)在生命周期的早期需要这些默认值覆盖只有在实际创建任何组件之前完成它们才会接受它们

// setting LAF
InteractiveTestCase.setLAF("Nimbus");
// tweak inputMap, immediately after setting the ui is fine
// uncomment the following line and it doesn't work
// new JPanel();
InputMap inputMap = (InputMap) UIManager.get("Button.focusInputMap");
inputMap.put(KeyStroke.getKeyStroke("SPACE"), "do-nothing");

如果 UIManager 那时没有返回 inputMap,我会认为这是您的自定义 LAF 的不当行为,并会尝试进一步挖掘为什么会发生这种情况。您可以尝试的另一件事是设置一个全新的 inputMap (这将具有在 LAF 切换中幸存下来的优势,因为它不是 UIResource,例如:

// setting LAF
InteractiveTestCase.setLAF("Nimbus");
// tweak inputMap, immediately after setting the ui is fine
InputMap inputMap = (InputMap) UIManager.get("Button.focusInputMap");
InputMap custom = new InputMap();
if (inputMap != null) {
    // copy all bindings to custom
    ...
} else {
    // add the binding we know of (as implementation detail)
    custom.put(KeyStroke.getKeyStroke("released SPACE"), "released");
}
// overwrite the binding you want to change
custom.put(KeyStroke.getKeyStroke("SPACE"), "do-nothing");
// set the custom map
UIManager.put("Button.focusInputMap", custom);
于 2012-09-21T09:12:46.007 回答
3

我不在计算机附近尝试此操作,但查看此处的 openjdk 7 源代码,默认情况下映射看起来是固定的。

一个可能的,但有点 hacky 的解决方案可能是创建并安装一个装饰器SynthStyleFactory,它在返回之前修改样式。

编辑:我已经更新了下面的代码示例,因为我有机会对此进行测试。它不能以原始形式工作,但更新后的代码对我有用。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.synth.Region;
import javax.swing.plaf.synth.SynthLookAndFeel;
import javax.swing.plaf.synth.SynthStyle;
import javax.swing.plaf.synth.SynthStyleFactory;

import sun.swing.plaf.synth.DefaultSynthStyle;

public class LnFTest {

    public static void main(String[] args) throws UnsupportedLookAndFeelException{

        SynthLookAndFeel laf = new SynthLookAndFeel();
        laf.load(LnFTest.class.getResourceAsStream("laf.xml"), LnFTest.class);
        UIManager.setLookAndFeel(laf);
        SynthLookAndFeel.setStyleFactory(new MyStyleFactory(SynthLookAndFeel.getStyleFactory()));


        JButton button = new JButton("Test");
        button.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                System.out.println("Action Performed");
            }
        });

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.add(button, BorderLayout.CENTER);
        frame.pack();

        frame.setVisible(true);

    }



}

class MyStyleFactory extends SynthStyleFactory {

    private SynthStyleFactory delegate;
    private Map overrides;

     public MyStyleFactory(SynthStyleFactory delegate){
         this.delegate = delegate;

         overrides = new HashMap();
         overrides.put("Button.focusInputMap", new UIDefaults.LazyInputMap(new Object[0]));
     }

     public SynthStyle getStyle(JComponent c, Region id) {
         SynthStyle style = delegate.getStyle(c, id);

         System.out.println("Style is a: " + style);

         if(style instanceof DefaultSynthStyle){
             ((DefaultSynthStyle)style).setData(overrides);
         }

         return style;

     }
}

编辑:我似乎无法在原始帖子中添加评论,所以为了澄清,我已经确认 UIManager.get("Button.focusInputMap") 在创建任何组件之前仅使用普通合成器返回 null。可能 Nimbus 正在覆盖这种行为。

 SynthLookAndFeel laf = new SynthLookAndFeel();
 UIManager.setLookAndFeel(laf);
 System.out.println(UIManager.get("Button.focusInputMap") == null); 
于 2012-09-20T22:52:24.863 回答