【问题标题】:How to turn off a key listener in NetBeans wizard panels?如何关闭 NetBeans 向导面板中的关键侦听器?
【发布时间】:2014-12-28 21:44:03
【问题描述】:

我为 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));

之后会生成类似的东西:

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

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

【问题讨论】:

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


    【解决方案1】:

    我不确定,但如果你知道是哪个 JComponent 导致了这种行为,试试这个:

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

    检查哪些击键绑定在JComponent

    suspectedComponent.getInputMap().keys()
    

    或者在父InputMap

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

    详情请参阅docs for InputMap

    【讨论】:

    • "none" 应该用于(禁用),而不是null,如here 所示。还要记住,有三个InputMaps。只需使用getInputMap(),就会隐式获取WHEN_FOCUSED
    • 确实,一方面,您所指的文档指出应该使用“无”。我昨天看到了。但是,另一方面,javadoc 声明应该使用 null:“如果 actionMapKey 为 null,这将删除 keyStroke 的当前绑定”。我宁愿相信 javadoc:docs.oracle.com/javase/8/docs/api/javax/swing/…
    • 嗯,你是对的。我懒得测试它,但我记得之前,尝试使用 null 对我不起作用。也许我错了。感谢您的参考:-)
    • 我知道我没疯。 There's a bug with null :-)
    【解决方案2】:

    一切正常,直到用户从列表中选择某个值,然后按 ENTER 键,然后我的面板进入下一个步骤 3。我附加了一个键 监听器列出类似 [...]

    如果您希望列表中的 Enter 键优先于默认的 Next -> 按钮,那么您必须使用 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();
                }
            });
        }
    }
    

    其他cmets

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

    【讨论】:

      猜你喜欢
      • 2017-04-06
      • 2021-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-20
      • 2013-01-04
      • 2021-08-02
      • 2019-01-24
      相关资源
      最近更新 更多