Неправильная позиция каретки в JTextPane?! Ошибка или ожидаемое поведение?
Я наткнулся на следующую проблему:
Я хочу прочитать символ в документе JTextComponent в расположении каретки компонента. Когда я использую JTextPane, символ, возвращенный в позиции каретки, не является правильным. Более подробно, возвращаемым символом является символ - позиция каретки минус номер строки!!! (позиция каретки - номер текущей строки). С другой стороны, когда я использую JTextArea, результат правильный... Чтобы продемонстрировать это, я реализовал пример программы, с которой вы можете играть.
Таким образом, большой вопрос, как я могу получить характер позиции каретки в случае JTextPane?
Почему JTextPane не возвращает ту же позицию каретки, что и JTextArea, и более того, почему символ, возвращаемый JTextPane, не тот, который мы можем видеть на экране? Является ли описанное поведение ошибкой?
Ниже вы можете найти код примера программы, а также скриншоты очень интересных и неожиданных результатов.
Использование JTextPane. Буква в позиции 17 CARET - это e. Нету...
http://img405.imageshack.us/img405/2746/jtextpane.jpg
Используйте JTextArea. Здесь у меня есть каретка в той же позиции, что и раньше, но теперь я получаю позицию каретки 20, и буква возврата \r\n (с является ожидаемой).
http://img809.imageshack.us/img809/5323/jtextarea.jpg
Вот код, с которым вы можете поиграть, чтобы увидеть это странное поведение:
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);
}
});
}
}
Спасибо за помощь!
PS я использую Java 6.
2 ответа
Использование
char result = testingArea.getDocument().getText(caretPosition,1).charAt(0);
скорее, чем
char result = testingArea.getText().charAt(caretPosition);
Я думаю, что в JTextPane EOL считается одним символом (\n, я полагаю), тогда как в JTextArea он считается двумя (\r\n).
Документация Oracle гласит:
Класс JEditorPane является основой для стилевых текстовых компонентов Swing и предоставляет механизм, с помощью которого вы можете добавить поддержку пользовательских текстовых форматов. Если вы хотите текст без стилей, используйте вместо этого текстовую область.
Таким образом, текстовая область основана только на данном тексте, поэтому все входные символы считаются. JEditorPane использовал StyledDocument, поэтому EOL может быть интерпретирован.