gpt4 book ai didi

java - 遍历启用和禁用的组件

转载 作者:行者123 更新时间:2023-11-29 07:38:21 25 4
gpt4 key购买 nike

焦点遍历似乎只适用于启用的 Swing 组件(使用 TABCTRL+TAB 制表符)。如何将启用和禁用的组件都视为重要的,并通过它们启用键盘遍历?

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

这里有一个示例表单来阐明设置/未设置状态(复选框和文本区域开始时未设置,而字段已设置):

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.JTextComponent;

public class TraverseDisabled extends JFrame {

public static final String VALUE_NOT_SET_MESSAGE = "Click to set this value.";
public static final String VALUE_SET_DEFAULT_MESSAGE = "Edit value or use CTRL + click to unset this value.";
public static final String VALUE_NOT_SET_DEFAULT_VALUE = "<not-set>";

private JPanel panel;
private JLabel label1;
private JTextField textfield1;
private JCheckBox checkbox1;
private JLabel label2;
private JTextArea textarea1;
private JButton button;

public TraverseDisabled() {
setTitle("Form");
initComponents();

pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

private void initComponents() {
panel = new JPanel();
panel.setLayout(new GridBagLayout());
setLayout(new BorderLayout());
add(panel);

GridBagConstraints gbc;

label1 = new JLabel("Field1:");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
panel.add(label1, gbc);

textfield1 = new JTextField(20);
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 0;
panel.add(textfield1, gbc);
textfield1.addMouseListener(new MouseAdapter() {

@Override
public void mouseClicked(MouseEvent e) {
onJComponentClicked(e, textfield1, null);
}

});

checkbox1 = new JCheckBox("Checkbox1");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.WEST;
panel.add(checkbox1, gbc);
checkbox1.addMouseListener(new MouseAdapter() {

@Override
public void mouseClicked(MouseEvent e) {
onJComponentClicked(e, checkbox1, false);
}

});
enableEditingForJCheckBoxComponent(checkbox1, false, false);

label2 = new JLabel("Area1:");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.NORTHWEST;
panel.add(label2, gbc);

textarea1 = new JTextArea(5, 20);
JScrollPane scrollPane1 = new JScrollPane(textarea1);
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 2;
panel.add(scrollPane1, gbc);
textarea1.addMouseListener(new MouseAdapter() {

@Override
public void mouseClicked(MouseEvent e) {
onJComponentClicked(e, textarea1, null);
}

});
enableEditingForJTextComponent(textarea1, false, VALUE_NOT_SET_DEFAULT_VALUE);

button = new JButton("Apply");
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 3;
gbc.anchor = GridBagConstraints.EAST;
panel.add(button, gbc);
}

private Object onJComponentClicked(java.awt.event.MouseEvent evt, JComponent component, Object previousValue) {
if (!component.isEnabled()) {
if (component instanceof JCheckBox) {
enableEditingForJCheckBoxComponent((JCheckBox)component, true, (Boolean)previousValue);
} else if (component instanceof JTextComponent) {
enableEditingForJTextComponent((JTextComponent)component, true, (String)previousValue);
}
evt.consume();
} else if (evt.isControlDown()) {
if (component instanceof JCheckBox) {
JCheckBox cb = (JCheckBox)component;
previousValue = !cb.isSelected();
enableEditingForJCheckBoxComponent((JCheckBox) component, false, (Boolean)previousValue);
} else if (component instanceof JTextComponent) {
previousValue = ((JTextComponent)component).getText();
enableEditingForJTextComponent((JTextComponent)component, false, VALUE_NOT_SET_DEFAULT_VALUE);
}
evt.consume();
}
return previousValue;
}

private void enableEditingForJTextComponent(JTextComponent textComponent, boolean enable, String text) {
if (!enable) {
textComponent.setEnabled(false);
textComponent.setText(text);
textComponent.setToolTipText(VALUE_NOT_SET_MESSAGE);
} else {
textComponent.setEnabled(true);
textComponent.setText(text);
textComponent.setToolTipText(VALUE_SET_DEFAULT_MESSAGE);
textComponent.requestFocusInWindow();
}
}

private void enableEditingForJCheckBoxComponent(JCheckBox checkBox, boolean enable, boolean value) {
if (!enable) {
checkBox.setEnabled(false);
checkBox.setSelected(value);
checkBox.setToolTipText(VALUE_NOT_SET_MESSAGE);
} else {
checkBox.setEnabled(true);
checkBox.setSelected(value);
checkBox.setToolTipText(VALUE_SET_DEFAULT_MESSAGE);
}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

public void run() {
new TraverseDisabled().setVisible(true);
}
});
}

}

最佳答案

我相信 Swing 使用的默认 FocusTraverslPolicy 最终会调用 Component 类中具有 final方法的方法:

final boolean canBeFocusOwner() {
// It is enabled, visible, focusable.
if (isEnabled() && isDisplayable() && isVisible() && isFocusable()) {
return true;
}
return false;
}

因此它肯定会检查以确保组件已启用。

所以我可以建议的唯一选择是尝试创建您自己的 FocusTraversalPolicy

Customizing Focus Traversal 上的 Swing 教程部分有一个示例,您可以使用/修改以满足您的要求。

关于java - 遍历启用和禁用的组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32994433/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com