gpt4 book ai didi

java - 为什么 JTextField.setText 会在 changedUpdate() 之前触发 DocumentListener 的 removeUpdate()?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:18:12 25 4
gpt4 key购买 nike

这是我的代码:

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。如何做到这一点?

最佳答案

这是字符串替换的预期行为。 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()文档:

Deletes the region of text from offset to offset + length, and replaces it with text. It is up to the implementation as to how this is implemented, some implementations may treat this as two distinct operations: a remove followed by an insert, others may treat the replace as one atomic operation.

所以要看文档实现。例如,PlainDocument 继承了 AbstractDocument 的基本实现。 PlainDocument 是文本字段的默认文档。

如果需要,您始终可以创建自己的文档实现,或者安装文档过滤器。参见 Using Text Components详细教程。但不确定您要实现的这种行为改变背后的原因是什么。

关于java - 为什么 JTextField.setText 会在 changedUpdate() 之前触发 DocumentListener 的 removeUpdate()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15209766/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com