java - 如何使用 DocumentFIlter 从另一个类设置 JTextField 的文本?

标签 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[] 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 block 中发生了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 实例,因为这将创建一个不显示的单独实例,而是传递适当的显示引用。

例如,

  ((AbstractDocument) textField.getDocument())
        .setDocumentFilter(new MyDocumentFilter(this)); //!!

class MyDocumentFilter extends DocumentFilter {
   private NewDemo n1;

   public MyDocumentFilter(NewDemo n1) {
      this.n1 = n1;
   }

但是,是的,也请遵循 MadProgrammer 的任何建议,因为他对 Swing 和 Java 了如指掌。另外,您应该避免使用 null 布局和使用 setBounds(...) 进行组件放置,因为这会导致 GUI 非常不灵活,虽然它们在一个平台上看起来不错,但在大多数其他平台上看起来很糟糕,或者屏幕分辨率,并且很难更新和维护。

<小时/>

编辑使用 MadProgrammer 的建议,考虑允许 GUI 将 PropertyChangeListener 添加到 DocumentFilter。这样,任何类都可以监听 DocumentFilter 的“状态”变化。在这里,我创建了一个名为“valid”的 boolean 状态,每当 boolean 变量发生变化时都会通知监听器。

例如:

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);
   }
}

关于java - 如何使用 DocumentFIlter 从另一个类设置 JTextField 的文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29054200/

相关文章:

java - 处理 Oracle DB 存储的 Java 类中的异常

java - 如何使用 Open nlp 的分块解析器提取名词短语

java - Swing 中的统一工具栏无法正常工作

java - getter 和 setter 与普通函数有何不同?

java - Java 中的 Getter 和 Setter

java - getter 和 setter 的替代方案

java - 优化 arrayRotateLeft 方法

java - 在字符串数组中找到最短的单词java

java - 如何在 Java 中刷新 GUI?

java - 在 Java 中手动重命名 JTree 节点