gpt4 book ai didi

java - 如何在 DocumentListener 运行时删除 JTextField 的内容?

转载 作者:行者123 更新时间:2023-12-01 19:29:16 25 4
gpt4 key购买 nike

对于以下代码,我收到 IllegalStateException(尝试在通知中进行变异):

private class DocumentHandler implements DocumentListener {
public void changedUpdate(DocumentEvent ev) {
// unused
}
public void insertUpdate(DocumentEvent ev) {
if(textInput.getText().equals("...")) {
JOptionPane.showMessageDialog(null, "...");
textInput.setText("");
}
}

为什么当 DocumentListener 处于 Activity 状态时我无法更改 TextField?

我尝试在 TextField 设置为“”时删除 DocumentListener,但这根本没有帮助。我知道之前有人问过非常类似的问题,但我没有得到答案......

谢谢

最佳答案

一般来说,在使用 DocumentListener 监听文档时,您不会更改文档的状态。我知道的两种可能的解决方案:

  • 在监听器中,将您希望在 Runnable 中进行更改的代码放入其中,并通过调用 SwingUtilities.invokeLater(yourRunnable) 将 Runnable 排队到 Swing 事件线程中。这是无耻的拼凑
  • 更好:不要使用 DocumentListener,而是使用 DocumentFilter,因为这种类型的监听器适合在文本在组件中可视化之前对文档进行更改。

不相关的附带问题:您的代码显示出令人担忧的耦合程度,因为您尝试从监听器内更改特定文本组件中的文本。 DocumentListeners 应该完全不知道它们所监听的文档的文本组件,并且事实上可能会被添加到多个文档中。

<小时/>

DocumentFilter 有 3 个需要重写的方法,并执行您期望它们执行的操作:您期望它们执行的操作:

  • insertString:在文档中插入字符串
  • 删除:从文档中删除文本
  • 替换:替换文档中的文本

此外,这些方法在文本组件呈现对文档的更改之前执行其操作。

因此,在我的方法覆盖中,我提取当前文档的文本,并使用参数创建新文本的外观,例如我所做的替换方法:

@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
throws BadLocationException {
String currentText = fb.getDocument().getText(0, fb.getDocument().getLength());
StringBuilder sb = new StringBuilder(currentText);

String newText = sb.replace(offset, offset + length, text).toString();

然后,我对 newText 进行 boolean 测试,看看它是否“好”,如果是,则调用 super 的方法,此处为 replace(...),传入所有参数。如果没有,如果 newText 未通过测试,那么我会从文档中删除所有文本并显示 JOptionPane。

所以在这个例子中,我使用它作为我的测试方法:

private boolean isTextOk(String text) {
return !BAD_TEXTS.contains(text);
}

它测试文本是否是任何不允许的字符串,这里“...”,“”,“oops”,“OOPS”,但它可以是您认为的任何字符串欲望。同样,如果文本传递了文本,则调用 super 的方法,否则删除文本:

if (isTextOk(newText)) {
super.replace(fb, offset, length, text, attrs);
} else {
badText(fb);
}

badText(fb) 的作用:

private void badText(FilterBypass fb) throws BadLocationException {
remove(fb, 0, fb.getDocument().getLength());
JOptionPane.showMessageDialog(null, "Don't do this!", "Bad Text Entered",
JOptionPane.WARNING_MESSAGE);
}
<小时/>

整个示例是:

import java.util.Arrays;
import java.util.List;
import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.PlainDocument;

@SuppressWarnings("serial")
public class ClearThreeDots extends JPanel {
private JTextField textField = new JTextField(40);

public ClearThreeDots() {
((PlainDocument) textField.getDocument()).setDocumentFilter(new MyDocFilter());
add(textField);
}

private static void createAndShowGui() {
ClearThreeDots mainPanel = new ClearThreeDots();

JFrame frame = new JFrame("Clear Three Dots");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MyDocFilter extends DocumentFilter {
private static final List<String> BAD_TEXTS = Arrays.asList("...", " ", "oops", "OOPS");

@Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
throws BadLocationException {
String currentText = fb.getDocument().getText(0, fb.getDocument().getLength());
StringBuilder sb = new StringBuilder(currentText);

String newText = sb.insert(offset, string).toString();

if (isTextOk(newText)) {
super.insertString(fb, offset, string, attr);
} else {
badText(fb);
}
}

@Override
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
String currentText = fb.getDocument().getText(0, fb.getDocument().getLength());
StringBuilder sb = new StringBuilder(currentText);

String newText = sb.replace(offset, offset + length, "").toString();

if (isTextOk(newText)) {
super.remove(fb, offset, length);
} else {
badText(fb);
}

}

@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
throws BadLocationException {
String currentText = fb.getDocument().getText(0, fb.getDocument().getLength());
StringBuilder sb = new StringBuilder(currentText);

String newText = sb.replace(offset, offset + length, text).toString();

if (isTextOk(newText)) {
super.replace(fb, offset, length, text, attrs);
} else {
badText(fb);
}

}

private boolean isTextOk(String text) {
return !BAD_TEXTS.contains(text);
}

private void badText(FilterBypass fb) throws BadLocationException {
remove(fb, 0, fb.getDocument().getLength());
JOptionPane.showMessageDialog(null, "Don't do this!", "Bad Text Entered",
JOptionPane.WARNING_MESSAGE);
}

}

关于java - 如何在 DocumentListener 运行时删除 JTextField 的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60300755/

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