javaswinglook-and-feelkey-bindingssynth

Default button input map in a synth look and feel?


I am trying to use the UIManager to get and clear some default key bindings so that the spacebar doesn't activate my JButtons, as explained here. Problem is, likely due to my synth look and feel, (InputMap)UIManager.get("Button.focusInputMap"); returns a null. Does anyone know of a way to easily clear components input maps some other way, or why the UIManager returns a null in this case? Any tips are appreciated, thanks beforehand.


Solution

  • I'm not near a computer to try this, but looking at the openjdk 7 source here, the mapping looks fixed by default.

    A possible, but slightly hacky, solution could be to create and install a decorator SynthStyleFactory that modifies the style prior to returning it.

    EDIT: I've updated the below code sample as I've had a chance to test this. It didn't work in it's original form, but the updated code worked for me.

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

    EDIT: I don't seem able to add a comment to the original post, so just to clarify, I had confirmed that UIManager.get("Button.focusInputMap") returned null with just plain Synth, prior to creating any components. Possibly Nimbus is overriding this behaviour.

     SynthLookAndFeel laf = new SynthLookAndFeel();
     UIManager.setLookAndFeel(laf);
     System.out.println(UIManager.get("Button.focusInputMap") == null);