Карта ввода кнопок по умолчанию в стиле синтезатора?

Я пытаюсь использовать UIManager для получения и очистки некоторых привязок клавиш по умолчанию, чтобы пробел не активировал мои JButtons, как объяснено здесь. Проблема в том, что, вероятно, из-за внешнего вида моего синтезатора (InputMap)UIManager.get("Button.focusInputMap"); возвращает null. Кто-нибудь знает способ легко очистить входные карты компонентов другим способом или почему UIManager возвращает нуль в этом случае? Любые советы приветствуются, заранее спасибо.


person SuperTron    schedule 17.09.2012    source источник
comment
workforme (nimbus, jdk6/7) — так что является вашим LAF? Похоже с ним что-то не так..   -  person kleopatra    schedule 21.09.2012
comment
весло назад: не работает ;-) InputMap не является нулевым, но замена привязок нажатых/отпущенных в нем не предотвращает срабатывание пробела на кнопку в Nimbus (как это происходит в обоих win и металл)   -  person kleopatra    schedule 21.09.2012


Ответы (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); 
person David Hutchison    schedule 20.09.2012
comment
getDefaultValue() является статическим и закрытым в SynthStyle, есть ли другие идеи о том, как получить входную карту? - person SuperTron; 21.09.2012
comment
Ой мой плохой. По ссылке openJDK 7, которую я разместил, SynthStyle имеет метод public Object get(SynthContext context, Object key), который просто вызывает этот частный статический метод. Он использует только ключ. - person David Hutchison; 22.09.2012
comment
хм, ну, я пробовал это, но я не могу понять, что использовать в качестве контекста: S, вызывая (InputMap)style.get(null, "Button.focusInputMap"), дает мне исключение нулевого указателя, хотя контекст не используется... - person SuperTron; 22.09.2012
comment
@SuperTron, я обновил образец кода после тестирования и нашел способ, который заставил его работать, по крайней мере, у меня. Я не знаю, получаете ли вы уведомления об изменениях ответов. - person David Hutchison; 24.09.2012
comment
единственный недостаток (препятствующий во многих контекстах), который я вижу, - это необходимость доступа к пакету sun.xx. - person kleopatra; 24.09.2012
comment
Я знаю. Глядя на API, он кажется странным классом. В исходном сообщении, поскольку это проанализированный LNF, он может не использовать этот класс и использовать его подкласс (ParsedSynthStyle), которого нет в пакете sun. - person David Hutchison; 24.09.2012
comment
Есть идеи, как заставить этот декоратор работать в JDK7? Кажется, они удаляют класс DefaultSynthStyle... - person SuperTron; 04.01.2014

Во-первых: мне нравится идея украшенного 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);
person kleopatra    schedule 21.09.2012
comment
+1 Как ни странно, мой предыдущий взгляд на это работает на Mac OS X с com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel. - person trashgod; 21.09.2012
comment
+1, 1. UIManager.getLookAndFeelDefaults().put("Xxx", "Xxx"), 2. не уверен для JButton, потому что я пробовал с JMenu(Item) и работает только в случае, если Nimbus L&F был uinstalled ..., 3. в этом случае я использовал putClientProperty("Xxx", "Xxx") с ButtonModel, - person mKorbel; 21.09.2012
comment
@mKorbel 1) не имело никакого значения 2) ну, я пробовал много перестановок - это была единственная, которая сработала :-) 3) не понимаю, ButtonModel не имеет к этому никакого отношения - person kleopatra; 21.09.2012
comment
@trashgod oioioioi ... еще один случай записи-один раз-отладки-везде ;-) На самом деле, я считаю поведение Nimbus (при выигрыше, как показано здесь) ошибкой: похоже, что он не слушает - или недостаточно слушает - к изменениям в свойствах менеджера. - person kleopatra; 21.09.2012