Я пытаюсь использовать UIManager для получения и очистки некоторых привязок клавиш по умолчанию, чтобы пробел не активировал мои JButtons, как объяснено здесь. Проблема в том, что, вероятно, из-за внешнего вида моего синтезатора (InputMap)UIManager.get("Button.focusInputMap");
возвращает null
. Кто-нибудь знает способ легко очистить входные карты компонентов другим способом или почему UIManager возвращает нуль в этом случае? Любые советы приветствуются, заранее спасибо.
Карта ввода кнопок по умолчанию в стиле синтезатора?
Ответы (2)
У меня нет рядом компьютера, чтобы попробовать это, но я смотрю на исходный код openjdk 7 здесь сопоставление выглядит фиксированным по умолчанию.
Возможным, но слегка хакерским решением может быть создание и установка декоратора 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 с помощью простого Synth до создания каких-либо компонентов. Возможно, Nimbus переопределяет это поведение.
SynthLookAndFeel laf = new SynthLookAndFeel();
UIManager.setLookAndFeel(laf);
System.out.println(UIManager.get("Button.focusInputMap") == null);
public Object get(SynthContext context, Object key)
, который просто вызывает этот частный статический метод. Он использует только ключ.
- person David Hutchison; 22.09.2012
(InputMap)style.get(null, "Button.focusInputMap")
, дает мне исключение нулевого указателя, хотя контекст не используется...
- person SuperTron; 22.09.2012
Во-первых: мне нравится идея украшенного StyleFactory, как это было предложено в другом ответе @David :-) - так что, если это сработает, я предлагаю использовать это направление.
В любом случае, не мог удержаться от небольшого эксперимента: похоже, что Nimbus (и, возможно, другие LAF на основе Synth) нуждаются в этих переопределениях по умолчанию чрезвычайно в начале жизненного цикла: они принимают их, только если они сделаны до любой компонент фактически создается
// 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);
com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel
.
- person trashgod; 21.09.2012
UIManager.getLookAndFeelDefaults().put("Xxx", "Xxx")
, 2. не уверен для JButton
, потому что я пробовал с JMenu(Item)
и работает только в случае, если Nimbus L&F
был uinstalled
..., 3. в этом случае я использовал putClientProperty("Xxx", "Xxx")
с ButtonModel
,
- person mKorbel; 21.09.2012