Reputation: 3
When select check box to set enable(false) on second text field and hit enter need to focus at third text field
if not select any check box then hit ENTER it can be focus on text field as flow.
I should add any code or how can I make it work
My GUI:
private void chk1ActionPerformed(java.awt.event.ActionEvent evt) {
// Set action perform for check box:
if(chk1.isSelected()){
p1.setEnabled(false);
} else{
p1.setEnabled(true);
}
}
private void chk2ActionPerformed(java.awt.event.ActionEvent evt) {
// Set action perform for check box:
if(chk2.isSelected()){
p2.setEnabled(false);
} else{
p2.setEnabled(true);
}
}
private void chk3ActionPerformed(java.awt.event.ActionEvent evt) {
// Set action perform for check box:
if(chk3.isSelected()){
p3.setEnabled(false);
} else{
p3.setEnabled(true);
}
}
private void p_numKeyPressed(java.awt.event.KeyEvent evt) {
// TODO add your handling code here:
if(evt.getKeyCode()==KeyEvent.VK_ENTER){
p1.requestFocus();
}
}
private void p1KeyPressed(java.awt.event.KeyEvent evt) {
// TODO add your handling code here:
if(evt.getKeyCode()==KeyEvent.VK_ENTER){
p2.requestFocus();
}
}
private void p2KeyPressed(java.awt.event.KeyEvent evt) {
// TODO add your handling code here:
if(evt.getKeyCode()==KeyEvent.VK_ENTER){
p3.requestFocus();
}
}
Upvotes: 0
Views: 660
Reputation: 3321
I think what you are looking for is the Focus Subsystem. This is responsible for the order in which components are getting focus when you press a focus traversal key. For example you can define what is the order of the components to get focus, and also add the check to transfer focus only to enabled components. What you also seem to want to do is to add the ENTER key as a focus traversal key (ie when pressing it, the focus will be transfered to another component - according to the current focus traversal policy). All this can be done via the focus subsystem.
The following code seems to do what you are asking, by utilizing the focus subsystem:
import java.awt.Component;
import java.awt.Container;
import java.awt.DefaultFocusTraversalPolicy;
import java.awt.GridLayout;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class FocusHopSystem {
public static class AbsoluteFocusTraversalPolicy extends DefaultFocusTraversalPolicy {
private final Component[] comps;
public AbsoluteFocusTraversalPolicy(final Component... comps) {
this.comps = comps.clone();
}
private int indexOf(final Component comp) {
for (int i = 0; i < comps.length; ++i)
if (comps[i] == comp)
return i;
return -1;
}
@Override
public Component getComponentAfter(final Container aContainer, final Component aComponent) {
final int aIndex = indexOf(aComponent);
if (aIndex < 0)
return null;
for (int i = 1; i < comps.length; ++i) {
final Component after = comps[(aIndex + i) % comps.length];
if (after != null && after.isDisplayable() && after.isVisible() && after.isEnabled())
return after;
}
return null;
}
@Override
public Component getComponentBefore(final Container aContainer, final Component aComponent) {
final int aIndex = indexOf(aComponent);
if (aIndex < 0)
return null;
for (int i = 1; i < comps.length; ++i) {
final Component before = comps[(aIndex - i + comps.length) % comps.length];
if (before != null && before.isDisplayable() && before.isVisible() && before.isEnabled())
return before;
}
return null;
}
@Override
public Component getFirstComponent(final Container aContainer) {
for (int i = 0; i < comps.length; ++i) {
final Component first = comps[i];
if (first != null && first.isDisplayable() && first.isVisible() && first.isEnabled())
return first;
}
return null;
}
@Override
public Component getLastComponent(final Container aContainer) {
for (int i = comps.length - 1; i >= 0; --i) {
final Component last = comps[i];
if (last != null && last.isDisplayable() && last.isVisible() && last.isEnabled())
return last;
}
return null;
}
@Override
public Component getDefaultComponent(final Container aContainer) {
return getFirstComponent(aContainer);
}
}
private static void createAndShowGUI() {
final String text = "0";
final int width = 12;
final JTextField tf1 = new JTextField(text, width),
tf2 = new JTextField(text, width),
tf3 = new JTextField(text, width),
tf4 = new JTextField(text, width);
final JCheckBox ck2 = new JCheckBox("jTextField2", true),
ck3 = new JCheckBox("jTextField3", true),
ck4 = new JCheckBox("jTextField4", true);
final JButton save = new JButton("Save");
ck2.addActionListener(e -> tf2.setEnabled(ck2.isSelected()));
ck3.addActionListener(e -> tf3.setEnabled(ck3.isSelected()));
ck4.addActionListener(e -> tf4.setEnabled(ck4.isSelected()));
final JPanel frameContents = new JPanel(new GridLayout(0, 5, 5, 5));
//First row:
frameContents.add(new JPanel());
frameContents.add(ck2);
frameContents.add(ck3);
frameContents.add(ck4);
frameContents.add(new JPanel());
//Second row:
frameContents.add(tf1);
frameContents.add(tf2);
frameContents.add(tf3);
frameContents.add(tf4);
frameContents.add(save);
//Make the other components unfocusable:
for (final Component comp: new Component[]{ck2, ck3, ck4, save})
comp.setFocusable(false);
//Make frameContents the focus cycle root:
frameContents.setFocusCycleRoot(true);
//Install our FocusTraversalPolicy to the cycle root:
frameContents.setFocusTraversalPolicy(new AbsoluteFocusTraversalPolicy(tf1, tf2, tf3, tf4));
//Add KeyEvent.VK_ENTER key to the focus traversal keys of the frameContents:
final Set forwardKeys = frameContents.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
final Set newForwardKeys = new HashSet(forwardKeys);
newForwardKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0));
frameContents.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, newForwardKeys);
final JFrame frame = new JFrame("Focus traversal test.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(frameContents);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
//Start focus on the first text field:
tf1.requestFocusInWindow();
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(FocusHopSystem::createAndShowGUI);
}
}
In the above example, I am adding the key ENTER as an alternative focus traversal key, aside from TAB.
As I found out, it's even simpler than the first sample code, and that's because the default focus traversal policy does what you are asking, ie allows only focusable-and-enabled components to gain focus and in the desired order. So we only need to make the unneeded components to non-focusable (ie the check-boxes and the button) and leave enabled the text-fields. Just add/set the ENTER key as a focus traversal key and you are good to go:
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class FocusHopSystem2 {
private static void createAndShowGUI() {
final String text = "0";
final int width = 12;
final JTextField tf1 = new JTextField(text, width),
tf2 = new JTextField(text, width),
tf3 = new JTextField(text, width),
tf4 = new JTextField(text, width);
final JCheckBox ck2 = new JCheckBox("jTextField2", true),
ck3 = new JCheckBox("jTextField3", true),
ck4 = new JCheckBox("jTextField4", true);
final JButton save = new JButton("Save");
ck2.addActionListener(e -> tf2.setEnabled(ck2.isSelected()));
ck3.addActionListener(e -> tf3.setEnabled(ck3.isSelected()));
ck4.addActionListener(e -> tf4.setEnabled(ck4.isSelected()));
final JPanel frameContents = new JPanel(new GridLayout(0, 5, 5, 5));
//First row:
frameContents.add(new JPanel());
frameContents.add(ck2);
frameContents.add(ck3);
frameContents.add(ck4);
frameContents.add(new JPanel());
//Second row:
frameContents.add(tf1);
frameContents.add(tf2);
frameContents.add(tf3);
frameContents.add(tf4);
frameContents.add(save);
//Make the other components unfocusable:
for (final Component comp: new Component[]{ck2, ck3, ck4, save})
comp.setFocusable(false);
//Make frameContents the focus cycle root:
frameContents.setFocusCycleRoot(true);
////Install the DefaultFocusTraversalPolicy to the cycle root:
//frameContents.setFocusTraversalPolicy(new DefaultFocusTraversalPolicy()); //This is not necessary in this case.
//Add KeyEvent.VK_ENTER key to the focus traversal keys of the frameContents:
final Set forwardKeys = frameContents.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
final Set newForwardKeys = new HashSet(forwardKeys);
newForwardKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0));
frameContents.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, newForwardKeys);
final JFrame frame = new JFrame("Focus traversal test.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(frameContents);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
//Start focus on the first text field:
tf1.requestFocusInWindow();
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(FocusHopSystem2::createAndShowGUI);
}
}
You may also read The AWT Focus Subsystem.
Upvotes: 2
Reputation: 324147
This is the way the Tab
key works by default. When you press Tab
focus will move to the next enabled component.
If you want to duplicate this functionality for the Enter
key then first you can create a custom Action
Action transfer = new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
Component c = (Component)e.getSource();
c.transferFocus();
}
};
By default the "Enter" key will invoke the ActionListener
added to the text field. So, now you can add this Action
to specific text fields:
...
textField1.addActionListener( transfer );
textField2.addActionListener( transfer );
Or you can replace the default Enter Action
of all the text fields by adding your custom Action
to the ActionMap
:
...
ActionMap am = (ActionMap)UIManager.get("TextField.actionMap");
am.put("notify-field-accept", transfer);
Upvotes: 1