Проблема переноса слов в JTextPane
Я использую JTextPane
в приложении для редактирования исходного кода вики. Я добавил в него простую функцию проверки орфографии, которая подчеркивает неправильно написанные слова, изменяя атрибуты персонажа на другой стиль с помощью StyledDocument.setCharacterAttributes
,
Используются только эти два стиля: по умолчанию и "неправильно введенный". Элемент управления текстового редактора выполняет перенос слов, что является ожидаемым поведением.
Моя проблема в том, что есть случаи (не всегда, но воспроизводимые с определенным вики-документом), изменение этого атрибута символа как-то отключает перенос слов. Более конкретно, я удаляю три строки из середины документа и при следующем запуске средства проверки орфографии, когда сбрасывает атрибуты символа в стиль по умолчанию (до повторного запуска проверки орфографии), функция переноса слов отключается, и остается, что путь. Если я отменю удаление, перенос слов возвращается к нормальному состоянию.
Закомментируем одну строку, которая сбрасывает стиль:
editorPane.getStyledDocument().setCharacterAttributes(0, editorPane.getStyledDocument().getLength(), defaultStyle, true);
решает проблему.
РЕДАКТИРОВАТЬ 1
Я извлек проблему в простой тестовый пример. Извините за длинную строку, этот пример текста важен для воспроизведения ошибки (она была рандомизирована):
package jtextpanebug;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.WindowConstants;
import javax.swing.text.Style;
public class DemoFrame extends javax.swing.JFrame {
private final JButton btResetStyle;
private final JScrollPane scrollPane;
private final JTextPane textPane;
private final Style defaultStyle;
public DemoFrame() {
// Creating a simple form with a scrollable text pane and a button
scrollPane = new JScrollPane();
textPane = new JTextPane();
btResetStyle = new JButton();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
// The text pane's text is the scrambled version of my original test data,
// it is important because the problem depends on the pane's text
// (not every text makes it wrong)
textPane.setText("= Gernela Stuff Dogo to Wnko Obuat Oebrfe Disytung hte Iidnividal Oitpcs =\n\n== Elmyonrogit ==\n\n'''memidtaie-ngiebhro opnits''' - 2 points, \nwihhc nac eb ense ot eb mmiieadte hnigeorbs fo haec othre. \nThere si no strict | cxeat defiintoin. \nEth etipcur owebl shsow sa an example optins dna the rispa \nienbg mimedtiea iebnghsor ear ncnoetced.\n\n[[Amieg:einogrhb_pinsot.pgn]]\n\n'''enihgorb optnsi distacne''' - het avaeegr of sdntaisce \nderemitedn by het mimeidate-hieobngr tonpi ipras. \n\n'''lalw''' - a iotpntes nepgesnietrr a llwa, with toerh orwds: 2 apraelll, \nevyr sloce sraufce picsee. Heer is an xamelpe. \nIt is eualgttandri ofr eterbt zisiuaitovlan.\n\n[[Gimae:llwa.npg]]\n\n'''addtaiilon emmory reeueimtnqr of na laigorthm''' - \n(eth kepa mmeory suaeg fo teh nltpiaciapo ndirug the excteouin of eht grlaotihm) - \n(hte moeymr sueag fo hte loragitmh befoer ro ftrea eht ucxeeiont of the laogrihmt)\n\n== Het Input Pnoitset Ash to Repnrsete Ufscear Arsnoelbay Elwl ==\n\nIf tno efisciped toehrwsie yb hte cdoritnpsei of an aoglirthm, \nhetn hte eqtunrmeersi of it are heste:\n\n* Ifsrt fo all the poisentt umst reprseent urfseac, not urvec ro uvomel or nayithng eesl.\n* Awlls aym otn eb tniehnr tanh at least 3 * fo ienhbgro-tpoin-sidenact.\n* Dseeg amy ton be rhserap tnha 70 grdesee (as het agnle fo eht trmeaial) nda husdol be ta tleas 290 redeseg (ni caes fo cnvocae eedgs).\n* Onpti edintsy amy ont vayr oto humc \n** Het angre fo the coall ption desitnsei of a igsenl pisnotte nutip ushold eb sallm. Ahtt is: teh orait of het oclla oitnp idsentise oarund any 2 ipnost lsdhou eb lmitied.\n** Hte lcoal noipt deisynt ushlod otn ahencg sdduelyn (gliftyscaiinn ni a hotsr idnsteac). \n\nYreftntunaoul the largoimths cna tno yb ethmsevesl \nhcekc these qutenmeserir nda usjt yden rnuning, \nso it si eth rseu's iyponerissbtil to ton extucee an raltghomi no a itseopnt \nthat does ont mete het aogitmlhr's terieseurmnq.\n\nIf eth rmeteriuqen fo na airlgmoth on its npuit is ont mte, then tobh hte ueavbhior nad hte srluet fo hte alghoritms si dinfeuned. \nTeh loirgamth amy nru rfo iinfntie long imet or rodpuce evry abd rselut, ro a eruslt htat oolsk good btu is nicrtroec. Ni htis scea rtehe si tno nay aguntreee toabu the tmniatreion of the iralgtmho ro eht lqutaiy fo the sreltu ecxept htat the nptapalcioi iwll ont carsh.\n");
scrollPane.setViewportView(textPane);
getContentPane().add(scrollPane);
btResetStyle.setText("Reset style");
btResetStyle.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
btResetStyleActionPerformed(evt);
}
});
getContentPane().add(btResetStyle);
pack();
// The default style, the problem happens when we reset the full document
// to it:
defaultStyle = textPane.addStyle("default", null);
}
private void btResetStyleActionPerformed(java.awt.event.ActionEvent evt) {
// When the button is pressed we reset the full document to the default
// style. In the original application this was periodically done as
// part of the spell checking
textPane.getStyledDocument().setCharacterAttributes(0, textPane.getStyledDocument().getLength(), defaultStyle, true);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new DemoFrame().setVisible(true);
}
});
}
}
Воспроизведение вопроса:
- Скомпилируйте и запустите класс выше
- Попробуйте изменить размер фрейма - перенос слов работает
- Найдите и удалите три строки, которые я скопировал ниже
- нажмите
Reset style
кнопка - Перенос слов отключен
* Онти единцы ами онт вайр ото хум ** Het Angre for the coll ption desitnsei igsenl pisnotte nutip ushold eb sallm. Ахтт это: о-о-о-о-о-о-о-о-ле-е-иссентес оарунд любые 2 ипостаси. ** Hote lcoal noipt deisynt ushlod otn ahencg sdduelyn (gliftyscaiinn ni hotsr idnsteac).
РЕДАКТИРОВАТЬ 2
Использование маркера вместо стилей решило мою проблему, но мне все еще интересно, что не так с оригинальным подходом.
1 ответ
Это похоже на ту же проблему, о которой я спрашивал здесь: Странная упаковка текста со стилизованным текстом в JTextPane с Java 7.
Насколько я знаю, это ошибка в Java 7, и она не документирована в Oracle Bug Parade. Я все еще не нашел обходного пути (использование маркера не вариант в моем случае).