如何在NetBeans向导面板中关闭键侦听器?

时间:2014-11-01 22:21:00

标签: java swing netbeans netbeans-platform netbeans-plugins

我为NetBeans IDE开发了一个简单的插件。我在向导面板TopComponenet上的默认键事件有一点问题:

例如:

我有一个包含3个步骤的向导。在第二步中,我有一个JTextField,其中用户放置了一些值,然后在此文本字段下方显示JList。一切都没问题,直到用户从列表中选择一个值,然后按键 ENTER 然后我的面板转到下一步3.我附上一个键监听器列出如下内容:

list = new JList(new PackagesListModel());
list.addKeyListener(new KeyAdapter() {
    @Override
    public void keyReleased(java.awt.event.KeyEvent evt) {
        int keyCode = evt.getKeyCode();
        if(keyCode == KeyEvent.VK_ENTER){
            JList list = (JList)evt.getSource();
            Object selectedPackage = list.getSelectedValue();
            typePackageField.setText((String)selectedPackage);
        }
    }
});

但是这个监听器可能是在向导的TopComponenet的默认监听器之后调用的。如何使用ENTER键阻止用户移动到下一步?

我不想要这个动作(当用户按下ENTER然后他们进入下一步)。

更新

转发给Kraal回答:

问题是我不知道我在哪里可以寻找一个JButton Next (以挫败一个听众)。这听起来很奇怪,但我是怎么写的。我使用Netbeans Plaform WizzardDescriptor生成一个Wizzard(有3个步骤)。 WizzardDescriptor来自包:

  org.openide.WizardDescriptor; // Dialogs API

我向他投了3个面板实例: WizardDescriptor.Panel 来自同一个包装:

  org.openide.WizardDescriptor // Dialogs API

看起来像:

    panels = new ArrayList<>();
    panels.add(new LayoutWizardPanel1(selectedLayout));
    panels.add(new LayoutWizardPanel2(selectedLayout));
    panels.add(new LayoutWizardPanel3(selectedLayout));
    WizardDescriptor wiz = new WizardDescriptor(new WizardDescriptor.ArrayIterator<>(panels));

之后会生成如下内容:

enter image description here

在我的程序中,我可以访问WizardDescriptor

 http://bits.netbeans.org/dev/javadoc/org-openide-dialogs/org/openide/WizardDescriptor.html

2 个答案:

答案 0 :(得分:3)

我不确定,但如果您知道哪个JComponent导致此行为,请尝试以下操作:

suspectedComponent.getInputMap().put(KeyStroke.getKeyStrokeForEvent(KeyEvent.VK_ENTER),"none");

检查哪些击键绑定在JComponent

suspectedComponent.getInputMap().keys()

或在父InputMap中:

suspectedComponent.getInputMap().getParent().keys()

有关详细信息,请参阅docs for InputMap

答案 1 :(得分:2)

  

一切正常,直到用户从列表中选择一个值而不是按ENTER键然后我的面板转到下一步3.我附上一个键   听众列出类似[...]

的内容

如果您希望列表中的 Enter 键优先于默认的 Next - &gt; 按钮,则必须使用Key binding附加操作你关注的列表:

KeyStroke enterKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
Action updateTextfieldAction = new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) {
        JList list = (JList)evt.getSource();
        Object selectedPackage = list.getSelectedValue();
        typePackageField.setText((String)selectedPackage );
    }
};

list = new JList(new PackagesListModel());
list.getInputMap().put(enterKeyStroke, "enter");
list.getActionMap().put("enter", updateTextfieldAction);

请注意,getInputMap()getInputMap(JComponent.WHEN_FOCUSED)的快捷方式。这意味着如果您的列表具有焦点并且按下 Enter 键,则将执行附加到此键击的操作。

通过这种方式,您的操作将始终优先于下一个按钮的操作,无论是此按钮是default button还是已使用WHEN_IN_FOCUSED_WINDOW使用键绑定附加了操作,如下所示:

JButton button = new JButton(nextStepAction);
button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(enterKeyStroke, "enter");
button.getActionMap().put("enter", nextStepAction);

nextStepAction将成为向导下一步的动作。

另见Key bindings vs. key listeners in Java


实施例

请在下面举例说明。请注意,如果您关注另一个组件但列出了默认操作。我已将按钮设置为框架的根窗格默认按钮,并且我使用WHEN_IN_FOCUSED_WINDOW附加了一项操作,以证明WHEN_FOCUSED操作优先于这些操作。

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class Demo {

    private JList list;
    private JTextField textField;

    private void createAndShowGUI() {

        KeyStroke enterKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);

        Action nextStepAction = new AbstractAction("Next") {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(null, "Going to step 3!", "Message", JOptionPane.INFORMATION_MESSAGE);
            }
        };

        Action updateTextfieldAction = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                textField.setText((String)list.getSelectedValue());
            }
        };

        list = new JList(new String[]{"Item 1", "Item 2", "Item 3"});
        list.setPrototypeCellValue("This is a list's prototype cell value.");
        list.getInputMap().put(enterKeyStroke, "enter");
        list.getActionMap().put("enter", updateTextfieldAction);

        textField = new JTextField(15);

        JPanel listPanel = new JPanel();
        listPanel.add(new JScrollPane(list));
        listPanel.add(textField);

        JButton button = new JButton(nextStepAction);
        button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(enterKeyStroke, "enter");
        button.getActionMap().put("enter", nextStepAction);

        JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
        buttonsPanel.add(button);

        JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(listPanel);
        frame.add(buttonsPanel, BorderLayout.PAGE_END);
        frame.getRootPane().setDefaultButton(button);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Demo().createAndShowGUI();
            }
        });
    }
}

其他评论

请注意,如果您想避免所有这些问题,可以在列表中附加ListSelectionListener并更新选择更改时的文本字段,而无需按 Enter 键。实际上,如果您有权访问下一步操作,则可以根据列表选择启用/禁用它。通过执行此操作,您将确保如果列表中未选择任何项目,则向导无法继续。恕我直言,这将是一个更优雅的方式来处理这种情况。有关详细信息,请参阅Selecting Items in a List