Положение каретки в JTextPane неверно?! Ошибка или ожидаемое поведение?

я столкнулся со следующей проблемой:

Я хочу прочитать символ в документе JTextComponent в месте каретки компонента. Когда я использую JTextPane, символ, возвращаемый в позиции курсора, не является правильным. Более подробно возвращаемый символ - это символ, позиция каретки минус номер строки!!! (Позиция каретки- номер текущей строки). С другой стороны, когда я использую JTextArea, результат правильный... Чтобы продемонстрировать это, я реализовал пример программы, с которой вы можете поиграть.

Итак, большой вопрос: как я могу получить символ позиции каретки в случае JTextPane?

Почему JTextPane не возвращает ту же позицию курсора, что и JTextArea, и, более того, почему символ, возвращаемый JTextPane, не тот, который мы видим на экране? Является ли описанное поведение ошибкой?

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

Использование JTextPane. Буква в позиции CARET 17 — e. Неа...

альтернативный текст

Используйте JTextArea. Здесь у меня есть каретка в той же позиции, что и раньше, но теперь я получаю позицию каретки 20, а обратная буква - \r\n (с ожидаемым).

альтернативный текст

Вот код, с которым вы можете поиграть, чтобы увидеть это странное поведение:

import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
import java.awt.event.*;

public class Example extends JFrame {
//  use this instead of JTextPane to see the difference

//  JTextComponent testingArea = new JTextArea(5,10);  
    JTextComponent testingArea = new JTextPane();
JButton button = new JButton("test");
JTextComponent resultArea = new JTextField(20);


public Example() {
    initialise();
    testingArea.setText("line1\r\nline2\r\nline3\r\nline4");
}


private void initialise() {
    testingArea.setPreferredSize(new Dimension(100,100));
    setLayout(new FlowLayout());
    getContentPane().add(testingArea);
    getContentPane().add(new JLabel("answer"));
    getContentPane().add(resultArea);
    getContentPane().add(button);
    button.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            try { 
                int caretPosition = testingArea.getCaretPosition();
                char result = testingArea.getText().charAt(caretPosition);
                resultArea.setText("Char at caretPosition " + caretPosition + " is " + result);
            }catch (Exception e2) {
                e2.printStackTrace();
                resultArea.setText("ERROR");
            }

        }
    });
    setDefaultCloseOperation(EXIT_ON_CLOSE);
}

public static void main(String[] args) {
    final Example ex = new Example();
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            ex.pack();
            ex.setVisible(true);

        }
    });
}
}

Спасибо за помощь!

P.S. Я использую Java 6.


person C.L.S    schedule 16.01.2012    source источник
comment
Спасибо всем (alain.janinm, StanislavL) за ценные ответы!   -  person C.L.S    schedule 16.01.2012


Ответы (2)


Использовать

char result = testingArea.getDocument().getText(caretPosition,1).charAt(0);

скорее, чем

char result = testingArea.getText().charAt(caretPosition);
person StanislavL    schedule 16.01.2012

Я думаю, что в JTextPane EOL считается как один символ (я полагаю, \n), тогда как в JTextArea он считается как два (\r\n).

В документации Oracle говорится:

Класс JEditorPane является основой для стилизованных текстовых компонентов Swing и предоставляет механизм, с помощью которого можно добавить поддержку пользовательских текстовых форматов. Если вам нужен текст без стиля, используйте вместо него текстовую область.

Таким образом, текстовая область основана только на заданном тексте, поэтому учитываются все вводимые символы. JEditorPane использовал StyledDocument, чтобы можно было интерпретировать EOL.

person alain.janinm    schedule 16.01.2012
comment
Ты прав; на символах Windows CR+LF по сравнению с абстрактным концом строки. - person Joop Eggen; 16.01.2012