有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java多个使用类属性的类似DocumentListener如何将它们压缩到一个侦听器?

我有一个类TestListeners,包含一些JTextFields和其他属性(这里是整数)。我希望属性在相应的JTextField文本更改时更新。因此,我添加了一些DocumentListener,但是这些监听器做的几乎完全相同,只是目标属性不同。目标是只有一个监听器可以添加到所有三个JTextField中,并且对于每个JTextField,应该处理相应的类属性

我发现以下问题帮助我将JTextField动态地输入到侦听器中,而无需在其中硬编码它们:

https://codereview.stackexchange.com/questions/25895/applying-documentlistener-on-multiple-jtextfield

但是我找不到在侦听器中动态引用应该更改的属性的方法。如果有人能帮我想办法,我会很高兴的

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class TestListeners extends JFrame {
    Color white = new Color(255, 255, 255);
    Color red = new Color(255, 200, 200);
    JTextField field1 = new JTextField("11111");
    JTextField field2 = new JTextField("22222");
    JTextField field3 = new JTextField("33333");
    int value1 = 0;
    int value2 = 0;
    int value3 = 0;

    public static void main(String[] args) {
        new TestListeners();
    }

    public TestListeners() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(new Dimension(150, 100));
        this.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();

        c.gridx++; this.add(field1, c);
        c.gridx++; this.add(field2, c);
        c.gridx++; this.add(field3, c);

        field1.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void removeUpdate(DocumentEvent e) {
                filterText(field1.getText());
            }

            @Override
            public void insertUpdate(DocumentEvent e) {
                filterText(field1.getText());
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                filterText(field1.getText());
            }

            private void filterText(String text) {
                try {
                    value1 = Integer.parseInt(text);
                    field1.setBackground(white);
                    System.out.println("value1 = " + value1);
                } catch (NumberFormatException ex) {
                    System.out.println("text in field1 is not an integer");
                    field1.setBackground(red);
                }
            }
        });

        field2.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void removeUpdate(DocumentEvent e) {
                filterText(field2.getText());
            }

            @Override
            public void insertUpdate(DocumentEvent e) {
                filterText(field2.getText());
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                filterText(field2.getText());
            }

            private void filterText(String text) {
                try {
                    value2 = Integer.parseInt(text);
                    field2.setBackground(white);
                    System.out.println("value2 = " + value2);
                } catch (NumberFormatException ex) {
                    System.out.println("text in field2 is not an integer");
                    field2.setBackground(red);
                }
            }
        });

        field3.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void removeUpdate(DocumentEvent e) {
                filterText(field3.getText());
            }

            @Override
            public void insertUpdate(DocumentEvent e) {
                filterText(field3.getText());
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                filterText(field3.getText());
            }

            private void filterText(String text) {
                try {
                    value3 = Integer.parseInt(text);
                    field3.setBackground(white);
                    System.out.println("value3 = " + value3);
                } catch (NumberFormatException ex) {
                    System.out.println("text in field3 is not an integer");
                    field3.setBackground(red);
                }
            }
        });

        this.setVisible(true);
    }
}

共 (2) 个答案

  1. # 1 楼答案

    您正在使用匿名类来实现DocumentListner

    当然,您可以创建一个新类

    public class MyDocumentListener implements DocumentListner {
    
      public MyDocumentListener (TestListeners parentFrame) {
         // either via getter or in your example:
    
         parentFrame.value3 = 123; // value3 is packed protected.
      }
     // copy paste your methods here.
    }
    

    您必须将对要更改的GUI项的引用传递给MyDocumentListener的新实例

    请注意,成员变量没有任何修饰符。因此,该成员受数据包保护。只要你的新类与TestListeners处于同一个打包状态,你就可以在没有getter的情况下访问它们。否则,为该值实现getter和setter

    可以通过实现适当的构造函数来实现这一点

    然后可以像这样添加DocumentListner

    field3.getDocument().addDocumentListener(new MyDocumentListner(this));
    

    我们必须将“this”传递给MyDocumentListner的新实例,以便新的侦听器能够从中访问字段


    或者,您可以创建一个由匿名类组成的对象:

    DocumentListner myListener = new DoucmentListener {
      // implement your methods here
    }
    

    然后你可以像这样把DocumentListener传递给你的字段:

    field3.getDocument().addDocumentListener(myListener);
    
  2. # 2 楼答案

    从关注监听器之间的共同点开始,它们会验证JTextField的状态,但也会保持最后一个有效值

    因此,您需要一个监听器,它可以从JTextField获取文本,可以根据当前文本更改其状态,并且可以保持最后一个有效值,比如

    public class VerifyHandler implements DocumentListener {
    
        private int value;
        private JTextField field;
    
        public VerifyHandler(JTextField field) {
            this.field = field;
        }
    
        public int getValue() {
            return value;
        }
    
        @Override
        public void insertUpdate(DocumentEvent e) {
            filterText();
        }
    
        @Override
        public void removeUpdate(DocumentEvent e) {
            filterText();
        }
    
        @Override
        public void changedUpdate(DocumentEvent e) {
            filterText();
        }
    
        private void filterText() {
            try {
                value = Integer.parseInt(field.getText());
                field.setBackground(white);
            } catch (NumberFormatException ex) {
                field.setBackground(red);
            }
        }
    
    }
    

    现在,坦白地说,对于已经实现的东西来说,这似乎是很多工作

    例如,您可以使用JSpinnerJFormattedTextField或事件DocumentFilter来阻止用户输入除所需内容以外的任何内容

    见:

    更多细节