I have a JTextPane
with an extended DefaultStyledDocument
. Updating the document takes about 2 minutes. Currently I am breaking it up into steps and updating on the swing thread with InvokeAndWait
for each step. I have a progress bar and a cancel button. The cancel button only triggers when there is a break between steps. Each step takes about 10 seconds so I need to wait up to 10 seconds to stop the processing of the document. Is there anyway to make this more responsive? I am displaying a JFrame
with the JTextPane
in a JScrollPane
when it is done. When it is finally rendered the scroll is very responsive and I can view the whole document. I do not want to display the JFrame
until the document is updated yet I want to continue to show the progress of the update. Any ideas on how to update the document and have Swing and/or the cancel button more responsive?
====== Edit in response to comments ====== In styled document using the append(text) method - setting styles for each line before appending.
public void append(String text)
{
append(text, textStyle, paragraphStyle);
}
public void append(String text, Style ts, Style ps)
{
try
{
int start = this.getLength();
int end = this.getLength()+text.length();
this.insertString(start, text, ts);
this.setParagraphAttributes(start, end, ps, true);
}
catch (BadLocationException e)
{
LOG.log(Level.SEVERE, "Bad location in append", e);
}
}
======== Edit ======== This is what my document update method looks like.
public void writeTextOutsideOfSwing(StatusDialog status, float statusPercentage)
{
final StringBuilder letter = new StringBuilder();
final ArrayList<IndexTextEntry>list = new ArrayList<>();
LOG.log(Level.INFO, "Updating document: {0}", entries.length);
setText("");
int step = (int)((status.getMaximum() * statusPercentage) / (double)entries.length);
for(int j = 0; j < entries.length; j++)
{
if(status.cancel) break;
final int index = j;
list.add(entries[j]);
if(list.size() == 100 || index == entries.length -1)
{
int first = index - list.size() + 2;
int last = index + 1;
status.setStatusBarText("Writing Concordance: Processing " + first + " - " + last + " of " + entries.length);
try
{
SwingUtilities.invokeAndWait(()->
{
for(int k = 0; k < list.size(); k++)
{
int i = index-list.size() + k;
if(!letter.toString().equals(list.get(k).getSortLetter()))
{
letter.setLength(0);
letter.append(list.get(k).getSortLetter());
String title = list.get(k).getSortLetterTitle(letter.toString());
appendLetter(title, i == 0);
}
else if(i > 0)
{
if(cf.getLineBetweenEntries())
{
clearTextAreaStyles();
setFontSize(cf.getLineBetweenEntriesFontSize());
append(" \n");
}
}
float indent = appendEntry(0, list.get(k));
appendSubEntries(indent, list.get(k));
}
});
}
catch(InterruptedException | InvocationTargetException ex)
{ LOG.log(Level.SEVERE, "Writing Concorder Interrupted", ex); }
list.clear();
}
status.increment(step);
}
LOG.info("Done updating docuemnt");
}
And these methods go with the write method:
private void appendSubEntries(float indent, IndexTextEntry entry)
{
for (IndexTextEntry subEntry : entry.getSubEntries())
{
float ind = appendEntry(indent, subEntry);
appendSubEntries(ind, subEntry);
}
}
private float appendEntry(float indent, IndexTextEntry entry)
{
setFontFamily(cf.getWordFormat().getFontFamily());
setFontSize(cf.getWordFormat().getFontSize());
setFontBold(cf.getWordFormat().getBold());
setFontItalic(cf.getWordFormat().getItalic());
switch (cf.getWordFormat().getAlignment())
{
case TextFormat.ALIGN_CENTER:
setFontAlignment(EnhancedTextArea.ALIGN_CENTER);
break;
case TextFormat.ALIGN_RIGHT:
setFontAlignment(EnhancedTextArea.ALIGN_RIGHT);
break;
default:
setFontAlignment(EnhancedTextArea.ALIGN_LEFT);
break;
}
float wi = indent + cf.getWordFormat().getIndentJAVA();
setLeftIndent(wi);
setFontColor(cf.getWordFormat().getColor());
append(entry.getConcordance().getTitle());
append("\n");
float li = 0;
for(ConcordanceLine line : entry.getConcordance().getLines())
li = appendLine(wi, line);
return li;
}
private float appendLine(float indent, ConcordanceLine line)
{
setFontFamily(cf.getLineFormat().getFontFamily());
setFontSize(cf.getLineFormat().getFontSize());
switch (cf.getLineFormat().getAlignment())
{
case TextFormat.ALIGN_CENTER:
setFontAlignment(EnhancedTextArea.ALIGN_CENTER);
break;
case TextFormat.ALIGN_RIGHT:
setFontAlignment(EnhancedTextArea.ALIGN_RIGHT);
break;
default:
setFontAlignment(EnhancedTextArea.ALIGN_LEFT);
break;
}
float li = indent + cf.getLineFormat().getIndentJAVA();
setLeftIndent(li);
setFontColor(cf.getLineFormat().getColor());
setFontBold(cf.getPageBold());
setFontItalic(cf.getPageItalic());
append(line.page + " ");
setFontBold(cf.getLineBold());
setFontItalic(cf.getLineItalic());
append(line.lead);
setFontBold(cf.getWordBold());
setFontItalic(cf.getWordItalic());
append(line.word);
setFontBold(cf.getLineBold());
setFontItalic(cf.getLineItalic());
append(line.trail);
append("\n");
return li;
}
ALL VARIABLES are resolved before get methods