Edit: The solution to question you think is a possible duplicate(java.lang.IllegalStateException while using Document Listener in TextArea, Java) is exactly what I have entered in the code to come to this problem. I used the 3 override methods when writing the custom DocumentListener. However, this did not solve the problem.
For some reason, this worked okay when using actionListener
(See here - Update JTextField.addActionListener without pressing "enter"). The issue with actionListener
was I had to hit "enter" every time I wanted the label to update. So someone suggested use DocumentListener
instead. Having done this. I am getting an error I cannot figure out, as well as really strange behavior.
Since the code is too large to post here, I have zipped up the project (using with Intellij and JRE 1.8) > https://www.dropbox.com/s/pf4hiuk9y0jby7y/FF7LevelUpStatCalculator.zip?dl=0
Isolated the code block for where the issue is happening (for quick review):
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();
}
}
}
);
}
Reproduce Issue(s):
Step 2: Select Cloud in the character combobox
Step 3: Enter integer digits and recognize issue(s)
I noticed it's complaining when trying to access an object and execute a setValue() method
on line #1338... Anyone have any ideas why this is happening?
Update:
DocumentFilter seems to be doing it correctly, as long as I comment out a line (that is needed when checking the rules of the max value). Here is the code thus far:
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();
}
}
}
);
}
I could still use some help with this.
Update 2: I started using SwingUtilities.invokeLater
as camickr suggested. It works with the line I commented out in the above code snippet, however, it sets it off into an infinite loop...
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();
}
}
}
);
}
I can't seem to get the combination of boolean flags set right to stop it from doing an infinite loop, but still execute the line System.out.println("run");
with every change made in the JTextField. If I change the if statement
from if (!newTextReplaceSet || !newTextInsertSet || newTextRemoveSet)
to if (!newTextReplaceSet || newTextInsertSet || newTextRemoveSet)
, it will go from executing System.out.println("run");
with an infinite loop, to only executing it once (and not again when another change is made to the JTextField
). Can anyone help me?