我想在用户输入无效值的文本字段上设置红色边框。即使用户没有编辑它们,此字段也可能具有无效值,例如DateFormatter上的空值。或NumberFormatter上的空值。这就是我使用FocusListener的原因。
以下是两个可以满足我需要的类,但是,当应用程序在没有用户输入的情况下设置或更改值时,该字段仍然显示为无效。
我不确定我是否应该使用“外观和感觉”作为解决方案,或者“行动”。在我试图实现这种需求的方式上,您是否看到了良好的OOP方法?
提前致谢。
public class Form {
private java.util.ArrayList<JComponent> list = new java.util.ArrayList();
private TextVerifier verifier;
public Form() {
verifier = new TextVerifier();
}
public void add(JComponent c) {
if (c instanceof JFormattedTextField) {
((JFormattedTextField)c).setFocusLostBehavior(JFormattedTextField.COMMIT);
c.addFocusListener(verifier);
}
}
public void clear() {
for (JComponent c : list) {
verifier.unmark(c);
}
}
}
public class TextVerifier implements FocusListener {
@Override
public void focusGained(FocusEvent e) {
}
@Override
public void focusLost(FocusEvent e) {
if (e.getSource() instanceof JFormattedTextField) {
JFormattedTextField field = (JFormattedTextField)e.getSource();
if (isValid(field)) {
unmark(field);
}
else {
mark(field);
}
}
}
public void mark(JComponent component) {
if (component!=null) {
component.setBorder(javax.swing.BorderFactory.createLineBorder(java.awt.Color.red, 1));
}
}
public void unmark(JComponent component) {
if (component!=null) {
component.setBorder(null);
}
}
public boolean isValid(JFormattedTextField field) {
JFormattedTextField.AbstractFormatter formatter = field.getFormatter();
if (formatter != null) {
try {
formatter.stringToValue(field.getText());
}
catch (java.text.ParseException e) {
return false;
}
}
return true;
}
}
答案 0 :(得分:0)
我更喜欢使用DocumentListener。为了解决您的问题,我认为这将是最好的方法。 请注意TextVerifier中的mark和unmark方法,以避免lookAndFeel出现问题,只更改文本字段的背景可能会更好,它看起来比文本字段上的红色边框更好。
public void add(JComponent c) {
if (c instanceof JFormattedTextField) {
((JFormattedTextField) c).setFocusLostBehavior(JFormattedTextField.COMMIT);
c.addFocusListener(verifier);
//Add the component to the document properties
((JFormattedTextField) c).getDocument().putProperty("owner", c);
//Change Verifier to implement DocumentListener. You wouldn't need focusListener in this case.
((JFormattedTextField) c).getDocument().addDocumentListener(verifier);
list.add(c);
}
}
以下完整代码:
import java.awt.BorderLayout;
import java.util.Random;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.text.NumberFormatter;
public class Form {
private java.util.ArrayList<JComponent> list = new java.util.ArrayList<>();
private TextVerifier verifier;
public Form() {
verifier = new TextVerifier();
}
public void add(JComponent c) {
if (c instanceof JFormattedTextField) {
((JFormattedTextField) c).setFocusLostBehavior(JFormattedTextField.COMMIT);
c.addFocusListener(verifier);
((JFormattedTextField) c).getDocument().putProperty("owner", c);
((JFormattedTextField) c).getDocument().addDocumentListener(verifier);
list.add(c);
}
}
public void clear() {
for (JComponent c : list) {
verifier.unmark(c);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
frame.getContentPane().add(panel, BorderLayout.CENTER);
Form form = new Form();
for (int i = 0; i < 5; i++) {
JLabel label = new JLabel("Number " + i + ": ");
JFormattedTextField field = new JFormattedTextField(new NumberFormatter());
panel.add(createLabelFieldPanel(label, field));
form.add(field);
}
JButton change = new JButton("Change");
change.addActionListener(e -> form.updateValues());
frame.getContentPane().add(change, BorderLayout.SOUTH);
frame.pack();
form.updateValues();
frame.setVisible(true);
}
private Random random = new Random();
private void updateValues() {
for (JComponent c : list) {
if (c instanceof JFormattedTextField) {
((JFormattedTextField) c).setValue(random.nextInt(100));
}
}
}
public static JPanel createLabelFieldPanel(final JComponent label, final JComponent field) {
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.add(label);
panel.add(field);
return panel;
}
}
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class TextVerifier implements FocusListener, DocumentListener {
@Override
public void focusGained(FocusEvent e) {
}
@Override
public void focusLost(FocusEvent e) {
if (e.getSource() instanceof JFormattedTextField) {
JFormattedTextField field = (JFormattedTextField) e.getSource();
if (isValid(field)) {
unmark(field);
} else {
mark(field);
}
}
}
private static final Color RED = hex2Rgb("fffeeeddd");
public static Color hex2Rgb(String colorStr) {
return new Color(
Integer.valueOf( colorStr.substring( 1, 3 ), 16 ),
Integer.valueOf( colorStr.substring( 3, 5 ), 16 ),
Integer.valueOf( colorStr.substring( 5, 7 ), 16 ) );
}
public void mark(JComponent component) {
if (component != null) {
component.setBackground(RED);
}
}
public void unmark(JComponent component) {
if (component != null) {
component.setBackground(Color.white);
}
}
public boolean isValid(JFormattedTextField field) {
JFormattedTextField.AbstractFormatter formatter = field.getFormatter();
if (formatter != null) {
try {
formatter.stringToValue(field.getText());
} catch (java.text.ParseException e) {
return false;
}
}
return true;
}
@Override
public void changedUpdate(DocumentEvent e) {
docChanged(e);
}
@Override
public void insertUpdate(DocumentEvent e) {
docChanged(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
docChanged(e);
}
private void docChanged(DocumentEvent e) {
if (e.getDocument().getProperty("owner") instanceof JFormattedTextField) {
JFormattedTextField field = (JFormattedTextField) e.getDocument().getProperty("owner");
if (isValid(field)) {
unmark(field);
} else {
mark(field);
}
}
}
}