这是我的代码:
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
。怎么做?
答案 0 :(得分: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);
}
}
如您所见,AbstractDocument.replace()
文档已执行AbstractDocument
。否则,执行remove()
和insert()
。
来自AbstractDocument.replace()文档:
删除文本区域,从offset到offset + length,和 用文字替换它。这取决于如何实现 实现后,一些实现可能会将其视为两个不同的 操作:删除后插入,其他人可以处理 替换为一个原子操作。
所以这取决于文档的实现。例如,PlainDocument
继承了AbstractDocument
的基本实现。 PlainDocument
是文本字段的默认文档。
如果需要,您可以随时创建自己的文档实现,也可以安装文档过滤器。有关详细信息,请参阅Using Text Components教程。但不确定,这个行为改变背后的原因是什么。