8

どのキーストロークがどのキーストロークに属するかを制御したいJcomponentJcomponentに関連付けられているデフォルトのキーストロークを削除して、他のお気に入りのキーストロークに置き換える方法も知りたいです。

私はこのオラクルのチュートリアルに従いました.JButtonの例が示されています.試してみましたがうまくいきました.

まさに私が試したのは、SPACEキーを削除することです。つまり、JComponent がSPACEプレスに応答しなくなります。

このコードを使用してSPACEキーを削除しました。

firstButton.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "none");

JComboBox についても同じことが言えます

sizesComboBox.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "none");

しかし、それは(JComboBox)がまだSPACEキーに応答していることです

私がプレスfirstButtonの効果を取り除いたことのために。SPACEキーを追加しましたが、キーボードのキーを押したときに が押されるようになりましたFので、反応しません(意図)。がフォーカスされていなくてもの押下が行われることに注意してください ( )firstButtonFSPACEFfirstButtonJComponent.WHEN_IN_FOCUSED_WINDOW

これは私の例を示す SSCCE コードです:
: 上記のコード行を意図的に 2 番目のボタン「secondButton」に追加しなかったためSPACE、デフォルトで応答します。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;

public class KeyStrokeTest extends JPanel
{

    JPanel widgetPanel;
    JPanel textAreaPanel;
    JButton firstButton;
    JButton secondButton;
    JTextArea textArea;
    JComboBox<Integer> sizesComboBox;

    public KeyStrokeTest()
    {
        firstButton = new JButton("First");
        firstButton.addActionListener(eventWatcher);
        firstButton.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "none");
        firstButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F"), "F Key");
        firstButton.getActionMap().put("F Key", eventWatcher);

        secondButton = new JButton("Second");
        secondButton.addActionListener(eventWatcher);

        sizesComboBox = new JComboBox<>();
        sizesComboBox.addItemListener(new itemListenerClass());
        for (int i = 1; i <= 8; i++)
        {
            sizesComboBox.addItem(i);
        }
        sizesComboBox.setSelectedIndex(0);
        sizesComboBox.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "none");


        textArea = new JTextArea(0, 0);
        JScrollPane scrollTextArea = new JScrollPane(textArea);
        scrollTextArea.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        textArea.setEditable(false);

        widgetPanel = new JPanel();
        textAreaPanel = new JPanel(new BorderLayout());

        widgetPanel.add(firstButton);
        widgetPanel.add(secondButton);
        widgetPanel.add(sizesComboBox);

        textAreaPanel.add(scrollTextArea, BorderLayout.CENTER);

        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, textAreaPanel, widgetPanel);
        splitPane.setDividerLocation(280);
        splitPane.setResizeWeight(.5d);
        this.setLayout(new BorderLayout());
        this.add(splitPane);
    }
    AbstractAction eventWatcher = new AbstractAction()
    {
        @Override
        public void actionPerformed(ActionEvent ae)
        {
            Object source = ae.getSource();
            if (source == firstButton)
            {
                textArea.append("First button clicked\n");
            }
            if (source == secondButton)
            {
                textArea.append("Second button clicked\n");
            }
        }
    };

    private class itemListenerClass implements ItemListener
    {

        @Override
        public void itemStateChanged(ItemEvent e)
        {
            if (e.getSource() == sizesComboBox)
            {
                if (textArea != null)
                {
                    textArea.append("Item " + sizesComboBox.getSelectedItem() + "\n");
                }
            }
        }
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("KeyStroke Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 300);
        frame.add(new KeyStrokeTest(), BorderLayout.CENTER);
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                UIManager.put("swing.boldMetal", Boolean.FALSE);
                createAndShowGUI();
            }
        });
    }
}

JComponent のデフォルトのキーストロークを制御したい理由SPACEは、すべての JComponentのデフォルトの効果を削除したいからです。ただしSPACE、フォーカスがどこにあっても を使用して、プレスに応答する 1 つのボタンを除いてJComponent.WHEN_IN_FOCUSED_WINDOW、別のコンポーネントをクリックできるようにします。 (そして、除外されたボタンからフォーカスを移動しても)、SPACEそのボタンへの影響は妨げられません。


別のポイント: 上記のコードをテストした場合、JComboBox からアイテムを選択すると 2 行が生成されることがわかります。アイテム「4」を選択すると、JTextArea の出力は次のようになります。

Item 4
Item 4

なぜ2つ??

ありがとう。

4

1 に答える 1

5

しかし、動作しません。(JComboBox) はまだ SPACE キーに応答します

同様のものを使用する必要がありJComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT InputMapます(お気づきかもしれませんが、KeyEventandを使用するとKeyStroke.getKeyStroke(int key,int modifier,boolean onRelease)読みやすく、間違いが起こりにくくなります。つまり、間違った文字列引数を入力するなどです)。

sizesComboBox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
        .put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0,false), "none");

私が見る限り、この理由はここでうまく説明されています:

コンポーネントは、フォーカスのあるコンポーネントを含んでいます (またはそのコンポーネントです)。この入力マップは、通常、複合コンポーネント (実装が子コンポーネントに依存するコンポーネント) に使用されます。たとえば、ユーザーが編集している場合でも上矢印キー (たとえば) を使用すると、選択したセルが変更されるようにJTable、すべてのバインディングを使用して作成します。WHEN_ANCESTOR_OF_FOCUSED_COMPONENT

JComboboxしたがって、複合コンポーネントであると推測されるため、特定のキーのすべての内部コンポーネント KeyBinding 機能を削除するには、正しいInputMap-が必要です。WHEN_ANCESTOR_OF_FOCUSED_COMPONENTSPACE

別のポイント: 上記のコードをテストした場合、JComboBox項目「4」を選択すると、次の 2 行が出力されるJTextAreaことに気付くでしょう。

Item 4
Item 4

なぜ2つ??

@mKorbel (彼のコメントに +1) が言ったように、2 つのイベントが発生する可能性があります。

  • アイテムの選択が解除されました
  • アイテムが選択された

これらのイベントは、新しい値を選択すると古い値が選択解除されるため、ペアで発生します。したがって、これを確認して適切に行動する必要があります。

@Override
public void itemStateChanged(ItemEvent e)
{
   if(e.getStateChange()==ItemEvent.SELECTED) { 
       //am item was selected do something
   }
}

その他の提案:

  • 電話setSizeをかけないでJFrameください。

  • 適切なLayoutManagerand/or overridegetPreferredSizeを使用して、コンテンツに適合する を返し、設定が表示される前およびコンポーネントを追加した後にDimension呼び出します。pack()JFrame

于 2013-01-27T12:53:04.170 に答える