hereで説明されているように、スペースバーが JButton をアクティブにしないように、UIManager を使用していくつかのデフォルトのキーバインディングを取得およびクリアしようとしています。問題は、おそらく私のシンセのルック アンド フィールが原因で(InputMap)UIManager.get("Button.focusInputMap");
、null
. コンポーネントの入力マップを他の方法で簡単にクリアする方法、またはこの場合に UIManager が null を返す理由を知っている人はいますか? 事前に感謝します。
2 に答える
まず、@Davidによる他の回答で提案されているように、装飾されたStyleFactoryのアイデアが好きです:-)-それがうまくいけば、その方向に進むことをお勧めします。
とにかく、少し実験することに抵抗できませんでした: Nimbus (およびおそらく他のシンセベースの 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 の誤動作と見なし、なぜそれが起こるのかをさらに掘り下げようとします。あなたが試すことができるもう1つのことは、まったく新しいinputMapを設定することです(これは、次のようなUIResourceではないため、LAFトグルを存続させるという利点があります。
// 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);
私はこれを試すためにコンピューターの近くにいませんが、ここで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")がプレーンなSynthでnullを返すことを確認しました。おそらく、ニンバスがこの動作をオーバーライドしています。
SynthLookAndFeel laf = new SynthLookAndFeel();
UIManager.setLookAndFeel(laf);
System.out.println(UIManager.get("Button.focusInputMap") == null);