问题
I developed a simple plugin for NetBeans IDE. I have a little problem with default key event on TopComponenet
of Wizard panel:
For example:
I have a wizard with 3 steps. In second step I have a JTextField
where user put some values and after that appear a JList
below this text field. Everything is okay until user choose a some value from list and than press key ENTER then my panel goes to next Step 3. I attach a key listener to list something like:
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);
}
}
});
But this listener probably is invoking after default listener of TopComponenet
on wizard. How can I prevent moving user to next step using ENTER key?
I don't want this action (when user press ENTER then they go to the next step).
UPDATE:
Forwarding to Kraal answer:
Problem is that i dont know where i can lookking for a JButton Next (to shuting down a listener). It sound strange but how i wrote. Im using a Netbeans Plaform WizzardDescriptor to generate a Wizzard (with 3 steps) . WizzardDescriptor is from package:
org.openide.WizardDescriptor; // Dialogs API
i puted to him a 3 instances of panels: WizardDescriptor.Panel from same package:
org.openide.WizardDescriptor // Dialogs API
it looks like:
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));
After this will generated something like:
in my program i have access to WizardDescriptor
http://bits.netbeans.org/dev/javadoc/org-openide-dialogs/org/openide/WizardDescriptor.html
回答1:
Everything is okay until user choose a some value from list and than press key ENTER then my panel goes to next Step 3. I attach a key listener to list something like [...]
If you want Enter key in your list has precedence over the default Next -> button then you have to use Key binding to attach an action to your list when it's focused:
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);
Note that getInputMap() is a shortcut for getInputMap(JComponent.WHEN_FOCUSED). This means that if your list has focus and Enter key is pressed, then the action attached to this key stroke will be performed.
By this way your action will always have precedence over the next button's action, either if this button is the default button or it has attached an action using key bindings using WHEN_IN_FOCUSED_WINDOW
like this:
JButton button = new JButton(nextStepAction);
button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(enterKeyStroke, "enter");
button.getActionMap().put("enter", nextStepAction);
Where nextStepAction
would be the action to go to wizard's next step.
See also Key bindings vs. key listeners in Java
Example
Please cosider the example below. Note if you focus another component but list the the default action is performed. I've set the button as frame's root pane default button and I've attached an action using WHEN_IN_FOCUSED_WINDOW
just to prove that WHEN_FOCUSED
action has precedence over those.
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();
}
});
}
}
Other comments
Please note that if you want avoid all this matter, you could attach a ListSelectionListener to your list and update the text field on selection change with no need to press Enter key at all. In fact if you have access to the next step action you could enable/disable it based on list selection. By doing this you'll be sure that wizard can't continue if no item is selected in your list. IMHO that would be a more elegant way to handle this situation. See Selecting Items in a List for further details.
回答2:
I'm not sure but if you know which JComponent
causes this behaviour, try this:
suspectedComponent.getInputMap().put(KeyStroke.getKeyStrokeForEvent(KeyEvent.VK_ENTER),"none");
To check which keystrokes are bound on a JComponent
:
suspectedComponent.getInputMap().keys()
Or in the parent InputMap
:
suspectedComponent.getInputMap().getParent().keys()
See the docs for InputMap for details.
来源:https://stackoverflow.com/questions/26693850/how-to-turn-off-a-key-listener-in-netbeans-wizard-panels