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.
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);
public Object get(SynthContext context, Object key)
which just calls that private static method. It only uses the key. –
Farquhar (InputMap)style.get(null, "Button.focusInputMap")
gives me a null pointer exception, even though the context is not used... –
Hawking First off: I like the idea of a decorated StyleFactory as suggested in the other answer, by @David :-) - so if that works out would suggest to use go that direction.
Anyway, couldn't resist experimenting a bit: looks like Nimbus (and possibly other Synth-based LAFs) need those defaults overrides extremely early in the life-cycle: they accept them only if done before any component is actually created
// 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");
If the UIManager doesn't return an inputMap at that point, I would regard that as a misbehaviour of your custom LAF and would try to dig further as to why that happens. Another thingy you could try is to set an entirely new inputMap (which would have the advantage of surviving a LAF toggle, as it isn't a UIResource, like:
// 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);
com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel
. –
Heisenberg UIManager.getLookAndFeelDefaults().put("Xxx", "Xxx")
, 2. not sure for JButton
because I tried with JMenu(Item)
and works only in case if Nimbus L&F
was uinstalled
..., 3. in this case I used putClientProperty("Xxx", "Xxx")
with ButtonModel
, –
Bingo 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);
public Object get(SynthContext context, Object key)
which just calls that private static method. It only uses the key. –
Farquhar (InputMap)style.get(null, "Button.focusInputMap")
gives me a null pointer exception, even though the context is not used... –
Hawking © 2022 - 2024 — McMap. All rights reserved.