【发布时间】:2017-05-02 13:06:33
【问题描述】:
编辑:您认为可能重复的问题的解决方案(java.lang.IllegalStateException while using Document Listener in TextArea, Java) 正是我在代码中输入的内容来解决这个问题。我在编写自定义 DocumentListener 时使用了 3 种覆盖方法。但是,这并没有解决问题。
由于某种原因,在使用 actionListener 时这可以正常工作(请参阅此处 - Update JTextField.addActionListener without pressing "enter")。 actionListener 的问题是每次我想要更新标签时都必须点击“输入”。所以有人建议改用DocumentListener。做了这件事。我遇到了一个我无法弄清楚的错误,以及非常奇怪的行为。
由于代码太大,无法在此处发布,我已将项目压缩(与 Intellij 和 JRE 1.8 一起使用)> https://www.dropbox.com/s/pf4hiuk9y0jby7y/FF7LevelUpStatCalculator.zip?dl=0
隔离了问题所在的代码块(以便快速查看):
private void setHpBaseStatsTextFieldAction(){
hpBaseStatsTextField.getDocument().addDocumentListener(
new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
updateStatGridLabels();
}
public void removeUpdate(DocumentEvent e) {
updateStatGridLabels();
}
public void changedUpdate(DocumentEvent e) {
//Plain text components do not fire these events
}
public void updateStatGridLabels() {
String currCharacter = charSelCombo.getSelectedItem().toString();
String checkBaseHpInGui = hpBaseStatsTextField.getText();
int baseHpInGui = 0;
if (isInteger(checkBaseHpInGui)){
baseHpInGui = Integer.parseInt(checkBaseHpInGui);
}
if ((!(currCharacter.equals(guiCharSelDefaultValue[unselectedDefaultElement]))) && (isInteger(checkBaseHpInGui))){
characters[getSelectedCharactersIndex()].setBaseHp(baseHpInGui);
hpBaseStatsTextField.setText(Integer.toString(characters[getSelectedCharactersIndex()].getBaseHp()));
setHpStatGridRowValues();
}
}
}
);
}
重现问题:
我注意到它在尝试访问对象并在第 1338 行执行 setValue() method 时出现抱怨...有人知道为什么会发生这种情况吗?
更新:
DocumentFilter 似乎做得正确,只要我注释掉一行(检查最大值规则时需要)。这是到目前为止的代码:
private void setHpBaseStatsTextFieldAction(){
((AbstractDocument) hpBaseStatsTextField.getDocument()).setDocumentFilter(
new DocumentFilter() {
public void replace(DocumentFilter.FilterBypass fb, int offset, int length,
String text, AttributeSet attrs) throws BadLocationException {
if (offset >= fb.getDocument().getLength()) {
System.out.println("Added: " + text);
} else {
String old = fb.getDocument().getText(offset, length);
System.out.println("Replaced " + old + " with " + text);
}
super.replace(fb, offset, length, text, attrs);
updateStatGridLabels();
}
public void insertString(DocumentFilter.FilterBypass fb, int offset,
String text, AttributeSet attr) throws BadLocationException {
System.out.println("Added: " + text);
super.insertString(fb, offset, text, attr);
updateStatGridLabels();
}
public void remove(DocumentFilter.FilterBypass fb, int offset, int length)
throws BadLocationException {
System.out.println("Removed: " + fb.getDocument().getText(offset, length));
super.remove(fb, offset, length);
updateStatGridLabels();
}
public void updateStatGridLabels() {
String currCharacter = charSelCombo.getSelectedItem().toString();
String checkBaseHpInGui = hpBaseStatsTextField.getText();
int baseHpInGui = 0;
if (isInteger(checkBaseHpInGui)){
baseHpInGui = Integer.parseInt(checkBaseHpInGui);
}
if ((!(currCharacter.equals(guiCharSelDefaultValue[unselectedDefaultElement]))) && (isInteger(checkBaseHpInGui))){
characters[getSelectedCharactersIndex()].setBaseHp(baseHpInGui);
//hpBaseStatsTextField.setText(Integer.toString(characters[getSelectedCharactersIndex()].getBaseHp()));
setHpStatGridRowValues();
}
}
}
);
}
我仍然需要一些帮助。
更新 2: 我开始按照 camickr 的建议使用 SwingUtilities.invokeLater。它适用于我在上面的代码 sn-p 中注释掉的行,但是,它将它设置为无限循环...
private void setHpBaseStatsTextFieldAction(){
((AbstractDocument) hpBaseStatsTextField.getDocument()).setDocumentFilter(
new DocumentFilter() {
boolean newTextReplaceSet = false;
public void replace(DocumentFilter.FilterBypass fb, int offset, int length,
String text, AttributeSet attrs) throws BadLocationException {
if (offset >= fb.getDocument().getLength()) {
System.out.println("Added: " + text);
} else {
String old = fb.getDocument().getText(offset, length);
System.out.println("Replaced " + old + " with " + text);
}
super.replace(fb, offset, length, text, attrs);
updateStatGridLabels();
newTextReplaceSet = true;
}
boolean newTextInsertSet = false;
public void insertString(DocumentFilter.FilterBypass fb, int offset,
String text, AttributeSet attr) throws BadLocationException {
System.out.println("Added: " + text);
super.insertString(fb, offset, text, attr);
updateStatGridLabels();
newTextInsertSet = true;
}
boolean newTextRemoveSet = false;
public void remove(DocumentFilter.FilterBypass fb, int offset, int length)
throws BadLocationException {
System.out.println("Removed: " + fb.getDocument().getText(offset, length));
super.remove(fb, offset, length);
updateStatGridLabels();
newTextRemoveSet = true;
}
public void updateStatGridLabels() {
String currCharacter = charSelCombo.getSelectedItem().toString();
String checkBaseHpInGui = hpBaseStatsTextField.getText();
int baseHpInGui = 0;
if (isInteger(checkBaseHpInGui)){
baseHpInGui = Integer.parseInt(checkBaseHpInGui);
}
if ((!(currCharacter.equals(guiCharSelDefaultValue[unselectedDefaultElement]))) && (isInteger(checkBaseHpInGui))){
characters[getSelectedCharactersIndex()].setBaseHp(baseHpInGui);
if (!newTextReplaceSet || !newTextInsertSet || newTextRemoveSet) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
System.out.println("run");
hpBaseStatsTextField.setText(Integer.toString(characters[getSelectedCharactersIndex()].getBaseHp()));
}
});
}
//hpBaseStatsTextField.setText(Integer.toString(characters[getSelectedCharactersIndex()].getBaseHp()));
setHpStatGridRowValues();
}
}
}
);
}
我似乎无法正确设置布尔标志的组合以阻止它执行无限循环,但仍然执行System.out.println("run"); 行,并在 JTextField 中进行每次更改。如果我将if statement 从if (!newTextReplaceSet || !newTextInsertSet || newTextRemoveSet) 更改为if (!newTextReplaceSet || newTextInsertSet || newTextRemoveSet),它将从以无限循环执行System.out.println("run"); 变为只执行一次(而不是在对JTextField 进行另一次更改时再次执行)。谁能帮帮我?
【问题讨论】:
-
您似乎在为正在进行的更改触发 documentEvent 时尝试对文档进行修改。在actionPerformed中,文档更改结束,没有冲突,那么。
-
@Laurent G - 如果有办法让它更新用户输入的每个数字,那就太好了。有什么方法可以用 Swing 做到这一点?
-
@FiddleFreak cf docs.oracle.com/javase/7/docs/api/javax/swing/text/…
-
@Berger 您认为可能重复的问题的解决方案正是我在代码中输入的内容来解决这个问题。我在编写自定义 DocumentListener 时使用了 3 种覆盖方法。但是,这并没有解决问题...