Unexpected StackOverflowError in KeyListener
- by BillThePlatypus
I am writing a program that can write sets of questions for review to a file for another program to read. The possible answers are typed into JTextFields at the bottom. It has code to ensure that there won't bew more than one blank JTextField at the end. When I type in answers, at varying points it will throw a StackOverflowError.
The stack trace:
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
at java.awt.AWTEventMulticaster.keyPressed(AWTEventMulticaster.java:232)
at java.awt.AWTEventMulticaster.keyPressed(AWTEventMulticaster.java:232)
at java.awt.AWTEventMulticaster.keyPressed(AWTEventMulticaster.java:232)
at java.awt.AWTEventMulticaster.keyPressed(AWTEventMulticaster.java:232)
and the code:
package writer;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import main.QuestionSet;
public class SetPanel extends JPanel implements KeyListener
{
private QuestionSet set;
private WriterPanel writer;
private JPanel top=new JPanel(new BorderLayout()),controls=new JPanel(new GridLayout(1,0)),answerPanel=new JPanel(new GridLayout(0,1));
private JSplitPane split;
private JTextField title=new JTextField();
private JTextArea question=new JTextArea();
private ArrayList<JTextField> answers=new ArrayList<JTextField>();
public SetPanel(QuestionSet s,WriterPanel writer)
{
super(new BorderLayout());
top.add(controls,BorderLayout.PAGE_START);
title.setFont(title.getFont().deriveFont(40f));
title.addKeyListener(new KeyListener(){
@Override
public void keyTyped(KeyEvent e) {
title.setText(WriterPanel.convertString(title.getText()));
}
@Override
public void keyPressed(KeyEvent e) {
title.setText(WriterPanel.convertString(title.getText()));
}
@Override
public void keyReleased(KeyEvent e) {
title.setText(WriterPanel.convertString(title.getText()));
}
});
title.getDocument().addDocumentListener(new DocumentListener(){
@Override
public void insertUpdate(DocumentEvent e) {
// TODO Auto-generated method stub
fitTitle();
}
@Override
public void removeUpdate(DocumentEvent e) {
// TODO Auto-generated method stub
fitTitle();
}
@Override
public void changedUpdate(DocumentEvent e) {
// TODO Auto-generated method stub
fitTitle();
}
});
top.add(title,BorderLayout.PAGE_END);
this.add(top,BorderLayout.PAGE_START);
question.setLineWrap(true);
question.setWrapStyleWord(true);
question.setFont(question.getFont().deriveFont(20f));
question.addKeyListener(new KeyListener(){
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
question.setText(WriterPanel.convertString(question.getText()));
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
question.setText(WriterPanel.convertString(question.getText()));
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
question.setText(WriterPanel.convertString(question.getText()));
}});
split=new JSplitPane(JSplitPane.VERTICAL_SPLIT,true,new JScrollPane(question),new JScrollPane(answerPanel));
split.setDividerLocation(150);
this.add(split,BorderLayout.CENTER);
answers.add(new JTextField());
answerPanel.add(answers.get(0));
answers.get(0).addKeyListener(this);
}
private void fitTitle()
{
if(title==null||title.getText().equals(""))
return;
//title.setText(WriterPanel.convertString(title.getText()));
String text=title.getText();
Insets insets=title.getInsets();
int width=title.getWidth()-insets.left-insets.right;
int height=title.getHeight()-insets.top-insets.bottom;
Font root=title.getFont().deriveFont((float)height);
FontMetrics m=title.getFontMetrics(root);
if(m.stringWidth(text)<width)
{
title.setFont(title.getFont().deriveFont((float)height));
return;
}
float delta=-100;
while(Math.abs(delta)>.1f)
{
m=title.getFontMetrics(root);
int w=m.stringWidth(text);
if(w==width)
break;
if(Math.signum(w-width)==Math.signum(delta)||root.getSize2D()+delta<0)
{
delta/=-10;
continue;
}
root=root.deriveFont(root.getSize2D()+delta);
}
title.setFont(root);
}
private void fixAnswers()
{
//System.out.println(answers);
while(answers.get(answers.size()-1).getText().equals("")&&answers.size()>1&&answers.get(answers.size()-2).getText().equals(""))
removeAnswer(answers.size()-1);
if(!answers.get(answers.size()-1).getText().equals(""))
{
answers.add(new JTextField());
answerPanel.add(answers.get(answers.size()-1));
answers.get(answers.size()-2).removeKeyListener(this);
answerPanel.revalidate();
}
answers.get(answers.size()-1).addKeyListener(this);
}
private void removeAnswer(int i)
{
answers.remove(i);
answerPanel.remove(i);
answerPanel.revalidate();
}
@Override
public void keyTyped(KeyEvent e)
{
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
fixAnswers();
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
Thank you in advance for any help.