7

これは私のコードです:

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Frame extends JFrame {

    private JTextField txt1 = new JTextField(10);
    private JTextField txt2 = new JTextField(10);
    private JButton btn = new JButton("Set Text");

    public Frame() {
        super("Latihan");
        setLayout(new FlowLayout());
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                txt1.setText("TEST"); txt2.setText("TEST2");
            }
        });

        txt1.getDocument().addDocumentListener(new TheDocumentListener("txt1"));
        txt2.getDocument().addDocumentListener(new TheDocumentListener("txt2"));

        add(txt1);
        add(txt2);
        add(btn);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }

    public static void main (String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Frame();
            }
        });
    }
}

class TheDocumentListener implements DocumentListener {

    private String source;

    public TheDocumentListener(String source) {
        this.source = source;
    }
    @Override
    public void insertUpdate(DocumentEvent e) {
        System.out.println("insertUpdate from " + source);
    }

    @Override
    public void removeUpdate(DocumentEvent e) {
        System.out.println("removeUpdate from " + source);
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
        System.out.println("changedUpdate from " + source);
    }
}

JButton を初めてクリックすると、以下のみinsertUpdate()が呼び出されます。

insertUpdate from txt1
insertUpdate from txt2

しかし、もう一度ボタンをクリックするremoveUpdate()と、前に呼び出されますinsertUpdate():

removeUpdate from txt1
insertUpdate from txt1
removeUpdate from txt2
insertUpdate from txt2

これは予想される動作ですか、それとも私のコードに問題がありますか?

insertUpdate実行時に呼び出されていた唯一のメソッドを作成できますJTextField.setTextか? removeUpdateユーザーがテキストフィールドのテキストを削除したときにのみ呼び出されることを確認したい。どうやってするか?

4

1 に答える 1

5

これは、文字列置換の予想される動作です。実際に行うことsetText()は、文字列全体を削除して新しいものを設定することです。の実装は次のJTextField.setText()とおりです。

public void setText(String t) {
    try {
        Document doc = getDocument();
        if (doc instanceof AbstractDocument) {
            ((AbstractDocument)doc).replace(0, doc.getLength(), t,null);
        }
        else {
            doc.remove(0, doc.getLength());
            doc.insertString(0, t, null);
        }
    } catch (BadLocationException e) {
    UIManager.getLookAndFeel().provideErrorFeedback(JTextComponent.this);
    }
}

ご覧のとおり、 docsAbstractDocument.replace()に対して実行されます。AbstractDocumentそれ以外の場合remove()insert()実行されます。

AbstractDocument.replace()ドキュメントから:

オフセットからオフセット + 長さまでのテキストの領域を削除し、テキストに置き換えます。これがどのように実装されるかは実装次第です。実装によっては、これを 2 つの異なる操作として扱う場合があります: 削除の後に挿入が続く場合と、置換を 1 つのアトミック操作として扱う場合があります。

したがって、ドキュメントの実装に依存します。PlainDocumentたとえば、 の基本的な実装を継承しAbstractDocumentます。APlainDocumentは、テキスト フィールドの既定のドキュメントです。

必要に応じて、独自のドキュメント実装をいつでも作成できます。ドキュメント フィルターをインストールすることもできます。詳細については、テキスト コンポーネントの使用に関するチュートリアルを参照してください。ただし、達成しようとしているこの動作の変更の背後にある理由は何ですか。

于 2013-03-05T00:41:17.023 に答える