我为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
答案 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。