Как обработать большой DefaultStyledDocument и поймать событие отмены?

У меня JTextPane с расширенным DefaultStyledDocument. Обновление документа занимает около 2 минут. В настоящее время я разбиваю его на шаги и обновляю нить качелей с InvokeAndWait для каждого шага. У меня есть индикатор выполнения и кнопка отмены. Кнопка отмены срабатывает только при перерыве между шагами. Каждый шаг занимает около 10 секунд, поэтому мне нужно подождать до 10 секунд, чтобы остановить обработку документа. Есть ли способ сделать это более отзывчивым? Я показываю JFrame с JTextPane в JScrollPane, когда это будет сделано. Когда он наконец отображается, прокрутка очень отзывчива, и я могу просмотреть весь документ. Я не хочу отображать JFrame, пока документ не будет обновлен, но я хочу продолжать показывать ход обновления. Любые идеи о том, как обновить документ и сделать Swing и/или кнопку отмены более отзывчивой?

====== Редактировать в ответ на комментарии ====== В стилизованном документе с использованием метода append(text) - установка стилей для каждой строки перед добавлением.

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);
    }
}

======== Изменить ======== Вот как выглядит мой метод обновления документа.

 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");
}

И эти методы идут с методом записи:

 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;
}

ВСЕ ПЕРЕМЕННЫЕ разрешаются до получения методов


person user1819780    schedule 23.10.2018    source источник
comment
..with an extended DefaultStyledDocument. Updating the document takes about 2 minutes - Почему все так долго? Мы понятия не имеем, что вы изменили, возможно, вам следует поработать над этим процессом. with InvokeAndWait for each step. - возможно, вам следует использовать invokeLater(). Я предполагаю, что invokeAndWait() заблокирует EDT, пока он ожидает завершения процесса.   -  person camickr    schedule 23.10.2018
comment
Если я использую вызов позже, процесс занимает столько же времени, сколько запирает качание. В документе много тысяч строк, и каждая строка имеет несколько стилей. Если бы вы могли предложить способ написания стилизованного документа с тысячами строк и несколькими стилями в каждой строке за пределами свинга, это было бы признательно.   -  person user1819780    schedule 23.10.2018
comment
Создайте любые строки с помощью StringBuilder вне потока событий, а затем поместите результат в модель в потоке событий. Для этого вы можете использовать SwingWorker, особенно пару методов публикации/обработки.   -  person Hovercraft Full Of Eels    schedule 23.10.2018
comment
Все строки создаются до того, как я начну — просто используя: int start = getLength(); int end = getLength()+text.length(); insertString(начало, текст, ts) setParagraphAttributes(начало, конец, ps, правда); чтобы добавить строки со стилем в документ --- Могу ли я как-то ускорить это? не уверен как?   -  person user1819780    schedule 23.10.2018
comment
Все еще не знаете, что такое много тысяч? Все еще не знаете, что такое 10 шагов? Вы обрабатываете данные 10 раз или пытаетесь обновлять их блоками по 10? Все еще не знаете, что значит много стилей? Все, что вы показываете, это установка атрибутов абзаца. Сколько времени занимает загрузка текстовой панели без какого-либо форматирования? Область, в которой вы вставляете одну строку за раз или блоки строк. Не похоже, что вы выполняете какой-либо анализ данных, поэтому я не понимаю, почему вставка текста и установка атрибутов параграфа вызовут проблему. Дайте нам лучшее представление о том, что вы делаете.   -  person camickr    schedule 23.10.2018
comment
FWIW, я попытался написать синтаксический документ, чтобы выделить ключевые слова и комментарии Java. Чтобы прочитать, разобрать, выделить исходный java-файл размером 5K строк, потребовалось 360 мс.   -  person camickr    schedule 23.10.2018
comment
Много тысяч — в моем тестовом примере это 10251 строка — это может быть больше или меньше в зависимости от документа. Я никогда не говорил 10 шагов — я сказал, что каждый шаг занимает около 10 секунд. В моем текущем тесте это примерно 13 раз - каждый шаг меняется из-за рекурсии, необходимой для прохождения текста --- я вставляю текст до тех пор, пока не изменится javax.swing.text.Style. затем я вставляю текст с новым стилем.   -  person user1819780    schedule 23.10.2018
comment
Мой текст больше похож на 200k - неважно - вы говорили строки, я говорю персонажи   -  person user1819780    schedule 23.10.2018
comment
Мой общий текст составил 200 тыс. строк с 5 тыс. строк. Итак, у меня такое же количество текста, но меньше строк. in my test case it is 10251 lines - так что, если вы удвоите строку и экстраполируете мою подсветку синтаксиса, это будет около 7 секунд. In my current test this is about 13 times - each step varies due to the recursion needed to flow through the text - поэтому время, затрачиваемое на вашу логику обработки, а не логику добавления подсветки. Мы не можем догадаться, что вы делаете, поэтому мы не можем предложить.   -  person camickr    schedule 23.10.2018
comment
Я вижу, что подсветка может идти быстро. Я имел в виду около 500 тыс. символов - изменение шрифта, цвета, размера, отступов абзаца и т. д. - В идеале я хотел бы сделать это вне Swing.   -  person user1819780    schedule 23.10.2018
comment
Я просто изменил свою логику, чтобы выделить ключевое слово и увеличить размер шрифта. Время увеличилось на 10 мс. Если каждый шаг занимает 10 секунд, то я вижу несколько вариантов: 1) улучшить производительность шага 2) разбить каждый шаг на обработку 500 строк за раз, что даст вам больше возможностей отменить шаг. Как было предложено, вы должны использовать SwingWorker и публиковать 500 строк за раз для обработки. См.: stackoverflow.com/questions/27332210/ для моего старого кода подсветки.   -  person camickr    schedule 23.10.2018
comment
Дополнительный код мне не помогает: 1) Я понятия не имею, что вы вводите данные. 2) код не исполняемый. 3) вы используете пользовательские классы. 4) Я понятия не имею, что делают все ваши методы setXXX(). 5) Я понятия не имею, почему вы вызываете метод setXXX() 8 раз в одном методе. В моем примере кода я показал вам, как использовать SimpleAttributeSet для группировки нескольких атрибутов.   -  person camickr    schedule 23.10.2018
comment
Спасибо camickr2 за помощь. Я вынес весь код обработки из потока Swing и сгенерировал ArrayList наборов текста и стилей. (более 35 000 фрагментов в моем тестовом примере). Затем я обрабатывал эти наборы (фрагменты) по 1000 за раз в потоке Swing. Кнопка отмены стала более отзывчивой, а время обработки сократилось примерно на 40%.   -  person user1819780    schedule 24.10.2018