Программисты JAVA общаются здесь
Anonymous
Как заставить Java текстовые компоненты распознавать пространства с нулевой шириной в качестве потенциальных линейных на
Сообщение
Anonymous » 04 окт 2025, 18:38
Я заметил, что компоненты, такие как jtexpane, jeditorpane и jtextarea, похоже, игнорируют пространства с нулевой шириной в тексте, который они отображают. Это проблема для меня, потому что я хотел бы отобразить тексты, в которых подавляющее большинство потенциальных линейных разбил будут указаны через пространства с нулевой шириной. Произойти.
Код: Выделить всё
class AdvancedLinewrapTextArea extends JTextArea
{
// Core functionality:
public void paintComponent(Graphics g)
{
String textToWrap = getText();
availableWidth = getWidth();
if (!textToWrap.equals(processedText) || availableWidth != processedWidth)
{
rewrap(textToWrap);
}
super.paintComponent(g);
}
int availableWidth;
String processedText;
int processedWidth;
void rewrap(String textToWrap)
{
int caretPosition = getCaretPosition();
textToWrap = textToWrap.substring(0, caretPosition) + CARET_MARK + textToWrap.substring(caretPosition);
permanentLines = fullyUnwrapLines(textToWrap);
String wrappedText = rewrapLines();
if (!wrappedText.equals(textToWrap))
{
updateTextTo(wrappedText);
}
}
String[] permanentLines;
final String CARET_MARK = "" + (char)0 + (char)0;
String[] fullyUnwrapLines(String text)
{
String[] temporaryLines = text.split(TEMPORARY_LINEBREAK);
String baseText = temporaryLines[0];
for (int i = 1; i < temporaryLines.length; i ++)
{
baseText += temporaryLines[i];
}
return baseText.split("\n");
}
String rewrapLines()
{
for (int i = 0; i < permanentLines.length; i ++)
{
calculateWrappingForLine(i);
}
processedWidth = availableWidth;
String completeText = permanentLines[0];
for (int i = 1; i < permanentLines.length; i ++)
{
completeText = completeText + "\n" + permanentLines[i];
}
return completeText;
}
void updateTextTo(String newText)
{
String[] preAndPostCaret = preAndPostCaret(newText);
newText = preAndPostCaret[0];
if (preAndPostCaret.length == 2)
{
newText += preAndPostCaret[1];
}
processedText = newText;
setText(newText);
setCaretPosition(preAndPostCaret[0].length());
}
final String TEMPORARY_LINEBREAK = "" + (char)0 + "\n" + (char)0;
void calculateWrappingForLine(int line)
{
wrappedLine = "";
lineLength = permanentLines[line].length();
sublineWidth = 0;
wordStart = 0;
wordEndGuess = 0;
while (wordStart < lineLength)
{
processNextWord(line);
}
permanentLines[line] = wrappedLine;
}
String wrappedLine;
int lineLength,
sublineWidth,
wordStart,
wordEndGuess;
String[] preAndPostCaret(String text)
{
String[] parts = text.split(TEMPORARY_LINEBREAK + CARET_MARK);
if (parts.length == 2)
{
parts[0] += TEMPORARY_LINEBREAK;
// because in a row of TEMPORARY_LINEBREAK and CARET_MARK the CARET_MARK would be 'found' too early
// resulting in the caret being placed within the TEMPORARY_LINEBREAK when the length of 'preCaret' is read
}
else
{
parts = text.split(CARET_MARK);
}
return parts;
}
void processNextWord(int line)
{
charInFocus = permanentLines[line].charAt(wordEndGuess);
while (charInFocus != null && !isWrappingSpace(charInFocus))
{
wordEndGuess ++;
charInFocus = (wordEndGuess < lineLength)? permanentLines[line].charAt(wordEndGuess) : null;
}
word = permanentLines[line].substring(wordStart, wordEndGuess);
wordWidth = width(word);
if (sublineWidth + wordWidth < availableWidth)
{
acknowledgeSpaceBehindWord();
wrappedLine += word;
sublineWidth += wordWidth;
}
else
{
splitLine();
}
wordStart = wordEndGuess;
}
Character charInFocus;
String word;
int wordWidth;
boolean isWrappingSpace(char c)
{
for (int i = 0; i < wrappingSpaces.length; i ++)
{
if (c == wrappingSpaces[i])
{
return true;
}
}
return false;
}
int width(String text)
{
measusringTape.setText(text);
return measusringTape.getPreferredSize().width;
}
void acknowledgeSpaceBehindWord()
{
if (charInFocus != null)
{
word += charInFocus;
wordWidth = width(word);
wordEndGuess ++;
}
}
void splitLine()
{
wrappedWord = (wrappedLine.length() > 0)? TEMPORARY_LINEBREAK : "";
while (wordWidth > availableWidth && word.length() > 1)
{
splitWord();
}
acknowledgeSpaceBehindWord();
wrappedWord += word;
wrappedLine += wrappedWord;
sublineWidth = wordWidth;
}
String wrappedWord;
char[] wrappingSpaces = new char[] {};
JLabel measusringTape = new JLabel();
void splitWord()
{
String subword = word.substring(0, word.length() * availableWidth / wordWidth);
while (width(subword) > availableWidth)
{
subword = subword.substring(0, subword.length() - 1);
}
if (subword.length() == 0)
{
subword += word.charAt(0);
}
while (width(subword + word.charAt(subword.length()))
Подробнее здесь: [url]https://stackoverflow.com/questions/79778059/how-to-make-java-text-components-recognize-zero-width-spaces-as-potential-linebr[/url]
1759592316
Anonymous
Я заметил, что компоненты, такие как jtexpane, jeditorpane и jtextarea, похоже, игнорируют пространства с нулевой шириной в тексте, который они отображают. Это проблема для меня, потому что я хотел бы отобразить тексты, в которых подавляющее большинство потенциальных линейных разбил будут указаны через пространства с нулевой шириной. Произойти.[code]class AdvancedLinewrapTextArea extends JTextArea { // Core functionality: public void paintComponent(Graphics g) { String textToWrap = getText(); availableWidth = getWidth(); if (!textToWrap.equals(processedText) || availableWidth != processedWidth) { rewrap(textToWrap); } super.paintComponent(g); } int availableWidth; String processedText; int processedWidth; void rewrap(String textToWrap) { int caretPosition = getCaretPosition(); textToWrap = textToWrap.substring(0, caretPosition) + CARET_MARK + textToWrap.substring(caretPosition); permanentLines = fullyUnwrapLines(textToWrap); String wrappedText = rewrapLines(); if (!wrappedText.equals(textToWrap)) { updateTextTo(wrappedText); } } String[] permanentLines; final String CARET_MARK = "" + (char)0 + (char)0; String[] fullyUnwrapLines(String text) { String[] temporaryLines = text.split(TEMPORARY_LINEBREAK); String baseText = temporaryLines[0]; for (int i = 1; i < temporaryLines.length; i ++) { baseText += temporaryLines[i]; } return baseText.split("\n"); } String rewrapLines() { for (int i = 0; i < permanentLines.length; i ++) { calculateWrappingForLine(i); } processedWidth = availableWidth; String completeText = permanentLines[0]; for (int i = 1; i < permanentLines.length; i ++) { completeText = completeText + "\n" + permanentLines[i]; } return completeText; } void updateTextTo(String newText) { String[] preAndPostCaret = preAndPostCaret(newText); newText = preAndPostCaret[0]; if (preAndPostCaret.length == 2) { newText += preAndPostCaret[1]; } processedText = newText; setText(newText); setCaretPosition(preAndPostCaret[0].length()); } final String TEMPORARY_LINEBREAK = "" + (char)0 + "\n" + (char)0; void calculateWrappingForLine(int line) { wrappedLine = ""; lineLength = permanentLines[line].length(); sublineWidth = 0; wordStart = 0; wordEndGuess = 0; while (wordStart < lineLength) { processNextWord(line); } permanentLines[line] = wrappedLine; } String wrappedLine; int lineLength, sublineWidth, wordStart, wordEndGuess; String[] preAndPostCaret(String text) { String[] parts = text.split(TEMPORARY_LINEBREAK + CARET_MARK); if (parts.length == 2) { parts[0] += TEMPORARY_LINEBREAK; // because in a row of TEMPORARY_LINEBREAK and CARET_MARK the CARET_MARK would be 'found' too early // resulting in the caret being placed within the TEMPORARY_LINEBREAK when the length of 'preCaret' is read } else { parts = text.split(CARET_MARK); } return parts; } void processNextWord(int line) { charInFocus = permanentLines[line].charAt(wordEndGuess); while (charInFocus != null && !isWrappingSpace(charInFocus)) { wordEndGuess ++; charInFocus = (wordEndGuess < lineLength)? permanentLines[line].charAt(wordEndGuess) : null; } word = permanentLines[line].substring(wordStart, wordEndGuess); wordWidth = width(word); if (sublineWidth + wordWidth < availableWidth) { acknowledgeSpaceBehindWord(); wrappedLine += word; sublineWidth += wordWidth; } else { splitLine(); } wordStart = wordEndGuess; } Character charInFocus; String word; int wordWidth; boolean isWrappingSpace(char c) { for (int i = 0; i < wrappingSpaces.length; i ++) { if (c == wrappingSpaces[i]) { return true; } } return false; } int width(String text) { measusringTape.setText(text); return measusringTape.getPreferredSize().width; } void acknowledgeSpaceBehindWord() { if (charInFocus != null) { word += charInFocus; wordWidth = width(word); wordEndGuess ++; } } void splitLine() { wrappedWord = (wrappedLine.length() > 0)? TEMPORARY_LINEBREAK : ""; while (wordWidth > availableWidth && word.length() > 1) { splitWord(); } acknowledgeSpaceBehindWord(); wrappedWord += word; wrappedLine += wrappedWord; sublineWidth = wordWidth; } String wrappedWord; char[] wrappingSpaces = new char[] {}; JLabel measusringTape = new JLabel(); void splitWord() { String subword = word.substring(0, word.length() * availableWidth / wordWidth); while (width(subword) > availableWidth) { subword = subword.substring(0, subword.length() - 1); } if (subword.length() == 0) { subword += word.charAt(0); } while (width(subword + word.charAt(subword.length())) Подробнее здесь: [url]https://stackoverflow.com/questions/79778059/how-to-make-java-text-components-recognize-zero-width-spaces-as-potential-linebr[/url]