Java 遍历启用和禁用的组件

Java 遍历启用和禁用的组件,java,swing,Java,Swing,焦点遍历似乎只适用于已启用的Swing组件(使用TAB或CTRL+TAB进行TAB)。如何将已启用和已禁用的组件视为重要组件,并通过它们启用键盘遍历 我为什么要这个?我有一个表单,其中每个textfield、textarea或复选框除了其值之外,还可能有一个set和unset状态。目前,用户需要使用鼠标单击来设置和取消设置组件(左键单击取消设置组件以进行设置,CTRL+左键单击设置组件以取消设置),但我也希望提供键盘访问来执行相同的操作。我选择这种机制的原因是空值可能有意义-空文本组件字符串是重

焦点遍历似乎只适用于已启用的Swing组件(使用TAB或CTRL+TAB进行TAB)。如何将已启用和已禁用的组件视为重要组件,并通过它们启用键盘遍历

我为什么要这个?我有一个表单,其中每个textfield、textarea或复选框除了其值之外,还可能有一个set和unset状态。目前,用户需要使用鼠标单击来设置和取消设置组件(左键单击取消设置组件以进行设置,CTRL+左键单击设置组件以取消设置),但我也希望提供键盘访问来执行相同的操作。我选择这种机制的原因是空值可能有意义-空文本组件字符串是重要的,不能用于表示“未设置”。我也不想在每个可设置值前面加一个复选框,因为那样看起来很尴尬

下面是一个示例表单,用于说明设置/未设置状态(复选框和文本区域以未设置开始,而字段以设置开始):

导入java.awt.BorderLayout;
导入java.awt.GridBagConstraints;
导入java.awt.GridBagLayout;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入javax.swing.JButton;
导入javax.swing.JCheckBox;
导入javax.swing.JComponent;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
导入javax.swing.JTextArea;
导入javax.swing.JTextField;
导入javax.swing.SwingUtilities;
导入javax.swing.text.JTextComponent;
公共类遍历禁用扩展JFrame{
public static final String VALUE\u NOT\u SET\u MESSAGE=“单击以设置此值。”;
public static final String VALUE\u SET\u DEFAULT\u MESSAGE=“编辑值或使用CTRL+单击取消设置此值。”;
公共静态最终字符串值\未\设置\默认\值=”;
私人JPanel小组;
私人JLabel标签1;
私有JTextField textfield1;
私人JCheckBox checkbox1;
私人JLabel标签2;
私人JTextArea TextArea 1;
私人按钮;
公共遍历可禁用(){
片名(“表格”);
初始化组件();
包装();
setLocationRelativeTo(空);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
私有组件(){
panel=新的JPanel();
panel.setLayout(新的GridBagLayout());
setLayout(新的BorderLayout());
添加(面板);
gridbaggbc;
label1=新的JLabel(“Field1:”);
gbc=新的GridBagConstraints();
gbc.gridx=0;
gbc.gridy=0;
gbc.anchor=GridBagConstraints.WEST;
面板。添加(标签1,gbc);
textfield1=新的JTextField(20);
gbc=新的GridBagConstraints();
gbc.gridx=1;
gbc.gridy=0;
面板.添加(文本字段1,gbc);
textfield1.addMouseListener(新的MouseAdapter(){
@凌驾
公共无效mouseClicked(MouseEvent e){
onJComponentClicked(e,textfield1,null);
}
});
checkbox1=新的JCheckBox(“checkbox1”);
gbc=新的GridBagConstraints();
gbc.gridx=0;
gbc.gridy=1;
gbc.anchor=GridBagConstraints.WEST;
面板。添加(复选框1,gbc);
复选框1.addMouseListener(新的MouseAdapter(){
@凌驾
公共无效mouseClicked(MouseEvent e){
onJComponentClicked(e,复选框1,false);
}
});
为JCheckboxComponent启用编辑(复选框1,false,false);
标签2=新的JLabel(“区域1:”);
gbc=新的GridBagConstraints();
gbc.gridx=0;
gbc.gridy=2;
gbc.anchor=gridbag.NORTHWEST;
面板。添加(标签2,gbc);
textarea1=新的JTextArea(5,20);
JScrollPane scrollPane1=新的JScrollPane(textarea1);
gbc=新的GridBagConstraints();
gbc.gridx=1;
gbc.gridy=2;
面板添加(滚动面板1,gbc);
textarea1.addMouseListener(新的MouseAdapter(){
@凌驾
公共无效mouseClicked(MouseEvent e){
onJComponentClicked(e,textarea1,null);
}
});
为JTextComponent启用编辑(textarea1,false,值\未\设置\默认值);
按钮=新按钮(“应用”);
gbc=新的GridBagConstraints();
gbc.gridx=1;
gbc.gridy=3;
gbc.anchor=gridbag.EAST;
面板。添加(按钮,gbc);
}
jComponentClicked上的私有对象(java.awt.event.MouseEvent evt、JComponent组件、对象previousValue){
如果(!component.isEnabled()){
if(JCheckBox的组件实例){
启用JCheckBox组件的编辑((JCheckBox)组件,true,(Boolean)previousValue);
}else if(JTextComponent的组件实例){
enableEditingForJTextComponent((JTextComponent)component,true,(String)previousValue);
}
evt.consume();
}else if(evt.isControlDown()){
if(JCheckBox的组件实例){
JCheckBox cb=(JCheckBox)组件;
previousValue=!cb.isSelected();
启用JCheckBox组件的编辑((JCheckBox)组件,false,(Boolean)previousValue);
}else if(JTextComponent的组件实例){
previousValue=((JTextComponent)component.getText();
enableEditingForJTextComponent((JTextComponent)组件,false,值\未\设置\默认值);
}
evt.consume();
} 
返回以前的值;
}
私有void启用编辑JTextComponent(JTextComponent textComponent,布尔启用,字符串文本){
如果(!启用){
textComponent.setEnabled(false);
textComponent.setText(text);
textComponent.setToolTipText(值\未\设置\消息);
}否则{
textComponent.setEnabled(t
final boolean canBeFocusOwner() {
    // It is enabled, visible, focusable.
    if (isEnabled() && isDisplayable() && isVisible() && isFocusable()) {
        return true;
    }
    return false;
}