Java Swing: GlyphView: StateInvariantError после удаления упорядоченного/неупорядоченного списка (HTMLDocument)

Я не думаю, что это новая проблема. Но кажется, что есть ошибка, которая возникает всякий раз, когда упорядоченный/неупорядоченный список в JTextPane (EditorKit -> HTMLEditorKit, Document -> HTMLDocument) удаляется полностью вниз до самого верха с помощью клавиши возврата. Ниже приведено исключение, вызванное методом getText() GlyphView.

Exception in thread "AWT-EventQueue-0" javax.swing.text.StateInvariantError: GlyphView: Stale view: javax.swing.text.BadLocationException: Invalid location

Я могу предоставить SSCCE для этого. Но смоделировать не очень сложно. Просто используйте JTextPane с набором моделей HTMLEditorKit и HTMLDOcument внутри него. Либо используйте пользовательское действие «InsertOrderedList», либо каким-либо образом вставьте строку

<HTML><HEAD></HEAD><BODY><UL><LI></LI></UL></BODY></HTML>

что приведет к вставке упорядоченного/неупорядоченного списка внутри текстовой панели.

Странные части этой ошибки заключаются в следующем:

  1. Как только вы начнете удалять символы (и если у вас есть строки под маркированным списком), символы будут удаляться до тех пор, пока вы не нажмете последний символ последнего элемента маркера. Как только вы достигаете этого, курсор просто отказывается двигаться вверх, и выдается ошибка GlyphView.

  2. Иногда случается так, что после того, как вы удалили большую часть символов, вы все равно не сможете удалить первую пулю из списка. Он просто висит, пока вы не нажмете ctrl + a, а затем назад.

Я видел эти ошибки почти во всех HTML-редакторах на основе Java, доступных в Интернете, за исключением JWebEngine, где такого поведения нет. К сожалению, JWebEngine не имеет открытого исходного кода, и поэтому я не могу заглянуть внутрь их кода, чтобы узнать, как они решили эту проблему.

Я предполагаю, что уведомление, поступающее из модели документа HTML, имеет некоторую проблему, из-за которой код позиционирования курсора работает неправильно. Я также просмотрел базу данных ошибок Sun, чтобы проверить, поднималась ли эта конкретная проблема, но не смог найти ни одной (хотя я видел довольно много ошибок, очень похожих на эту). Также я очень уверен, что кто-то, должно быть, заметил это раньше и обратил на это внимание команды Swing.

Кто-нибудь, работающий с частью Swing (особенно текстовой), знает, поднималась ли эта проблема с Sun или есть ли какое-либо известное обходное решение, которое было найдено для смягчения проблемы?

Хотя возможно, что пользователь по-прежнему может удалять списки с панели с помощью выбора мыши, отсутствие возможности сделать то же самое с помощью клавиши Backspace кажется очень странным.

SSCCE теперь подключен. Чтобы воспроизвести ошибку, пожалуйста. следуйте шагам, как показано на прилагаемом рис.

  1. Добавьте строку текста. Затем добавьте 2/3 элемента списка, нажав кнопку над текстовой панелью. Теперь поместите курсор в конец последнего символа последнего маркера и продолжайте нажимать всю клавишу возврата, пока все символы не будут удалены.

Наблюдаемое поведение: последняя пуля будет висеть (не будет удалена) и будет выдано исключение (как указано выше)

Ожидается: никаких исключений, и содержимое текстовой области должно быть очищено.

public class Test {
    static final JFrame frame = new JFrame ();
    static final JTextPane textPane = new JTextPane ();

    static EditorKit kit;
    static JButton listButton;

    public static void createAndShowGUI () {
        //Create frame
        frame.setSize(400, 600);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(null);

        //Customize text pane visual properties
        textPane.setSize(300, 500);
        textPane.setLocation(50, 50);

        //customize text pane non visual properties
        kit = new CustomEditorKit ();
        textPane.setEditorKitForContentType("text/html", kit);
        textPane.setContentType("text/html");

        Action[] actions = ((HTMLEditorKit) kit).getActions();
        Action action = null;
        for (int i = 0; i < actions.length; i++) {
            action = actions [i];
            if (action.getValue(Action.NAME).equals("InsertUnorderedList")) {
                break;
            }
        }
        listButton = new JButton (action);
        listButton.setText("List");
        listButton.setSize(100, 20);
        listButton.setLocation(100, 10);
        listButton.setVisible(true);

        /* Add button and text pane to frame */
        frame.add(listButton);
        frame.add(textPane);
    }

    public static void main(String[] args) {
        try {
            EventQueue.invokeAndWait(new Runnable () {
                @Override
                public void run() {
                    createAndShowGUI ();
                }
            });
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    static class CustomEditorKit extends HTMLEditorKit {
        @Override
        public Document createDefaultDocument () {
            return new HTMLDocument (this.getStyleSheet());
        }
    }
}

Проблема удаления маркеров TextPane


person user396089    schedule 29.01.2012    source источник
comment
Прилагается SSCCE. Вы можете добавить несколько строк в верхней части текстовой панели, затем вставить несколько маркеров, а затем поместить курсор в конец последнего символа последнего маркера и начать нажимать клавишу возврата. Все содержимое будет удалено, но первая пуля останется, и появится исключение.   -  person user396089    schedule 30.01.2012
comment
В Java 7 (Windows) не выдается исключение (без ошибки), но происходит следующее явление. Возврат удаляет предшествующие символы, но курсор остается после первого маркера даже при удалении символов перед <ul><li>. Можно удалить пулю с помощью клавиши удаления. Это похоже на ложное размещение курсора. Я думаю, то же самое происходит и с <b> e.a. а там нормально. Так что остается небольшой баг.   -  person Joop Eggen    schedule 28.02.2012
comment
Не могли бы вы попробовать, убедившись, что строка внутри выделенного слова переносится? Кажется, я понял, что вы имеете в виду. В случае, если строка внутри маркера не переносится по словам, исключение не выдается, но вы все равно можете видеть, что курсор не движется вверх.   -  person user396089    schedule 28.02.2012
comment
Да, теперь я получаю исключение BadLocationException. Спасибо, хороший снимок экрана Ubuntu.   -  person Joop Eggen    schedule 28.02.2012
comment
Это определенно похоже на проблему с кодом GapContent Java Swing. Код позиционирования курсора здесь работает некорректно. Свинг-гуру, помогите пожалуйста!   -  person user396089    schedule 29.02.2012


Ответы (1)


я использовал это

action=new HTMLEditorKit.InsertHTMLTextAction("test", "<UL><LI><P>\n</P></LI></UL>", HTML.Tag.BODY, HTML.Tag.UL);

вместо действия по умолчанию в вашем примере, чтобы обеспечить правильную структуру.

У меня работает нормально. (Победа 7, Ява 1.6)

person StanislavL    schedule 02.03.2012
comment
Станислав: спасибо за обновление. Я попробовал ваш код сегодня, и, похоже, он хорошо справляется с основным случаем. Сейчас я не вижу исключения. Но есть еще один пограничный случай, когда код дает сбой - и это предположим, что после добавления маркера и строки (которое слово переносится), я помещаю курсор в начало следующего абзаца, а затем добавляю еще несколько строк и удаляю все символы, начинающиеся с конца. В этом случае все идет нормально, пока я не достигну начала абзаца, который был добавлен после элемента маркера. Курсор отказывается двигаться вверх, и я снова вижу исключение неправильного местоположения. - person user396089; 05.03.2012
comment
Я почему-то чувствую, что все это связано с классом GapContent, который реализует буфер Gap. Скорее всего некорректно работает код позиционирования курсора. - person user396089; 05.03.2012