Java 如何使用DocumentFIlter为另一个类的JTextField设置文本?
在下面的示例中,我创建了两个texfield。在第一个文本字段上写入时,如果用户键入了空格或数字,则应在另一个文本字段_1上显示消息。但一旦用户输入了数字/空格,它就会给出java.lang.NullPointerExceptionJava 如何使用DocumentFIlter为另一个类的JTextField设置文本?,java,swing,getter-setter,documentfilter,Java,Swing,Getter Setter,Documentfilter,在下面的示例中,我创建了两个texfield。在第一个文本字段上写入时,如果用户键入了空格或数字,则应在另一个文本字段_1上显示消息。但一旦用户输入了数字/空格,它就会给出java.lang.NullPointerException public class NewDemo extends JFrame { private JPanel p1; private JTextField textField,textField_1; public static void main(String[] a
public class NewDemo extends JFrame {
private JPanel p1;
private JTextField textField,textField_1;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
NewDemo frame = new NewDemo();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public NewDemo() {
setTitle("New Demo");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 500, 500);
p1 = new JPanel();
p1.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(p1);
p1.setLayout(null);
textField = new JTextField();
textField.setBounds(70, 71, 86, 20);
p1.add(textField);
textField.setColumns(10);
JLabel lblNewLabel = new JLabel("");
lblNewLabel.setBounds(70, 96, 86, 14);
p1.add(lblNewLabel);
textField_1 = new JTextField();
textField_1.setBounds(204, 71, 86, 20);
p1.add(textField_1);
textField_1.setColumns(10);
System.out.println("before calling");
((AbstractDocument) textField.getDocument()).setDocumentFilter(new MyDocumentFilter());
System.out.println("AfterCalling");
}
public JTextField getTextField_1() {
return textField_1;
}}
这里是第二个类MyDocumentFilter,其中replace方法的else块中出现java.lang.NullPointerException错误
class MyDocumentFilter extends DocumentFilter {
private NewDemo n1;
@Override
public void replace(FilterBypass fb, int i, int i1, String string, AttributeSet as) throws BadLocationException {
System.out.println("Starting: replace Method");
for (int n = string.length(); n > 0; n--)
char c = string.charAt(n - 1);
System.out.println(c);
if (Character.isAlphabetic(c)) {
System.out.println("In if: replace method");
super.replace(fb, i, i1, String.valueOf(c), as);
} else {
System.out.println("Not allowed:BEFORE");
n1.getTextField_1().setText("not allowed");//***HERE IS THE ERROR
System.out.println("Not allowed:AFTER");
}
}
}
@Override
public void remove(FilterBypass fb, int i, int i1) throws BadLocationException {
System.out.println("In :remove method");
super.remove(fb, i, i1);
}
@Override
public void insertString(FilterBypass fb, int i, String string, AttributeSet as) throws BadLocationException {
System.out.println("In: insterString Method");
super.insertString(fb, i, string, as);
}}
DocumentFilter需要对显示的NewDemo GUI对象的引用。不要像其他人建议的那样创建一个
新的NewDemo
实例,因为这将创建一个未显示的单独实例,而是传递适当的显示引用
e、 g
及
但是,是的,还要遵循MadProgrammer的任何建议,因为他对Swing和Java了如指掌。此外,您还应避免使用空布局和使用setBounds(…)
进行组件放置,因为这会导致非常不灵活的GUI,虽然它们在一个平台上看起来不错,但在大多数其他平台或屏幕分辨率上看起来很糟糕,并且很难更新和维护
<>强>编辑< /强>使用MadProgrammer的建议,考虑允许GUI向文档过滤器添加PrimeTyeLististor。这样,任何类都可以侦听DocumentFilter的“状态”中的更改。在这里,我创建了一个名为“valid”的布尔状态,该状态在布尔变量更改时通知侦听器 例如:
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
import javax.swing.text.*;
public class NewDemo extends JPanel {
private static final long serialVersionUID = 1L;
private JTextField textField, textField_1;
private static void createAndShowGui() {
NewDemo mainPanel = new NewDemo();
JFrame frame = new JFrame("New Demo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
public NewDemo() {
setLayout(new GridLayout(1, 0, 5, 5));
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
textField = new JTextField();
textField.setColumns(10);
add(textField);
textField_1 = new JTextField();
textField_1.setColumns(10);
add(textField_1);
MyDocumentFilter docFilter = new MyDocumentFilter(); // !!
((AbstractDocument) textField.getDocument()).setDocumentFilter(docFilter); // !!
docFilter.addPropertyChangeListener(MyDocumentFilter.VALID,
new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String text = ((Boolean) evt.getNewValue()) ? "Allowed"
: "Not Allowed";
textField_1.setText(text);
}
});
}
}
class MyDocumentFilter extends DocumentFilter {
public static final String VALID = "valid";
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
this);
private boolean valid = true;
@Override
public void replace(FilterBypass fb, int i, int i1, String string,
AttributeSet as) throws BadLocationException {
for (int n = string.length(); n > 0; n--) {
char c = string.charAt(n - 1);
System.out.println(c);
if (Character.isAlphabetic(c)) {
super.replace(fb, i, i1, String.valueOf(c), as);
setValid(true);
} else {
setValid(false);
}
}
}
@Override
public void remove(FilterBypass fb, int i, int i1)
throws BadLocationException {
super.remove(fb, i, i1);
}
@Override
public void insertString(FilterBypass fb, int i, String string,
AttributeSet as) throws BadLocationException {
super.insertString(fb, i, string, as);
}
public boolean isValid() {
return valid;
}
public void setValid(boolean valid) {
boolean oldValue = this.valid;
boolean newValue = valid;
this.valid = valid;
pcSupport.firePropertyChange(VALID, oldValue, newValue);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener l) {
pcSupport.addPropertyChangeListener(propertyName, l);
}
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener l) {
pcSupport.removePropertyChangeListener(propertyName, l);
}
}
修改UI的状态不是
DocumentFilter
的责任。相反,它应该提供状态出错的通知(或者您想知道的任何其他情况),并让代理决定应该做什么
public interface DocumentFilterListener {
public void documentFilterValidationFailed(DocumentFilter filter, String message);
}
public class MyDocumentFilter extends DocumentFilter {
private DocumentFilterListener filterListener;
public MyDocumentFilter(DocumentFilterListener filterListener) {
this.filteristener = filterListener;
}
@Override
public void replace(FilterBypass fb, int i, int i1, String string, AttributeSet as) throws BadLocationException {
System.out.println("Starting: replace Method");
for (int n = string.length(); n > 0; n--)
char c = string.charAt(n - 1);
System.out.println(c);
if (Character.isAlphabetic(c)) {
System.out.println("In if: replace method");
super.replace(fb, i, i1, String.valueOf(c), as);
} else if (filterListener != null) {
System.out.println("Not allowed:BEFORE");
filterListener.documentFilterValidationFailed(this, "not allowed");
System.out.println("Not allowed:AFTER");
}
}
}
@Override
public void remove(FilterBypass fb, int i, int i1) throws BadLocationException {
System.out.println("In :remove method");
super.remove(fb, i, i1);
}
@Override
public void insertString(FilterBypass fb, int i, String string, AttributeSet as) throws BadLocationException {
System.out.println("In: insterString Method");
super.insertString(fb, i, string, as);
}
}
然后,您只需实现接口的需求
((AbstractDocument) textField.getDocument()).setDocumentFilter(
new MyDocumentFilter(new DocumentFilterListener() {
public void documentFilterValidationFailed(DocumentFilter filter, String message) {
getTextField_1().setText(message);
}
}));
例如。不要在DocumentFilter中修改组件的状态,这不是筛选器的职责。当然,如果您想知道筛选器何时失败,请让筛选器引发某种事件,您可以监听并采取适当的措施actions@MadProgrammer当前位置我试图把你的建议纳入我的答案中。谢谢编辑:你也是!谢谢你。它起作用了。但是你能给我解释一下为什么我们使用公共MyDocumentFIlter(NewDemo n1)方法以及它是如何在这里工作的吗?谢谢,当然不用了。但是我应该使用什么来代替
setBounds
&null布局
?请提供任何示例,以便我能更好地理解。再次感谢。我需要你的帮助。在这个程序中,当我要输入数字值或空格时,它会显示“不允许”(但它是永久的),如果我想使它像“在按下数字/空格后,它会显示“不允许”,但在这之后,如果我按下任何字符,那么“不允许”“应该被移除。怎么做?你能用上面的代码对它进行编辑吗?谢谢@hovercraftfullofelsokie。再次感谢你。事实上,我对PropertyChangeListener知之甚少。但是,如果在理解过程中出现任何问题,将通过java.docs发布评论。@user1995161:另外,请查看并更新程序员的替代侦听器代码。“他对荡秋千的了解比你我可能学到的还要多。”哈弗克拉夫特弗洛费尔斯:是的,当然。好的。听起来不错。你们在编码方面真是太快了。在这两者之间,我应该引用什么,以便我在DocumentListener、Filter、Validation和property listener等方面做得更好?非常感谢你的回答和对我问题的良好回答。我想需要2-3个多小时才能理解你和气垫船发布的内容。
public interface DocumentFilterListener {
public void documentFilterValidationFailed(DocumentFilter filter, String message);
}
public class MyDocumentFilter extends DocumentFilter {
private DocumentFilterListener filterListener;
public MyDocumentFilter(DocumentFilterListener filterListener) {
this.filteristener = filterListener;
}
@Override
public void replace(FilterBypass fb, int i, int i1, String string, AttributeSet as) throws BadLocationException {
System.out.println("Starting: replace Method");
for (int n = string.length(); n > 0; n--)
char c = string.charAt(n - 1);
System.out.println(c);
if (Character.isAlphabetic(c)) {
System.out.println("In if: replace method");
super.replace(fb, i, i1, String.valueOf(c), as);
} else if (filterListener != null) {
System.out.println("Not allowed:BEFORE");
filterListener.documentFilterValidationFailed(this, "not allowed");
System.out.println("Not allowed:AFTER");
}
}
}
@Override
public void remove(FilterBypass fb, int i, int i1) throws BadLocationException {
System.out.println("In :remove method");
super.remove(fb, i, i1);
}
@Override
public void insertString(FilterBypass fb, int i, String string, AttributeSet as) throws BadLocationException {
System.out.println("In: insterString Method");
super.insertString(fb, i, string, as);
}
}
((AbstractDocument) textField.getDocument()).setDocumentFilter(
new MyDocumentFilter(new DocumentFilterListener() {
public void documentFilterValidationFailed(DocumentFilter filter, String message) {
getTextField_1().setText(message);
}
}));