Почему JTextArea и TextLayout переносят слова по-разному? - PullRequest
0 голосов
/ 04 апреля 2011

У нас есть приложение, которое рисует текст, но затем отображает JTextArea, чтобы пользователь мог редактировать текст, когда он нажимает на текст. Однако упаковка между этими двумя компонентами обработки текста отличается. Они используют одинаковую ширину, текстовую строку и шрифт.

Для рисования текста я использую учебник по Java, который, как я видел, использовался другими в связанных вопросах здесь и на других форумах. Вот эта часть кода:

FontRenderContext frc = g2d.getFontRenderContext();
TextLayout layout;
AttributedString attrString = new AttributedString(myText);
AttributedCharacterIterator charIterator;
int paragraphStart;
int paragraphEnd;
LineBreakMeasurer lineMeasurer;
float breakWidth;
float drawPosX;
float drawPosY;

attrString.addAttribute(TextAttribute.FONT, myFont);
charIterator = attrString.getIterator();
paragraphStart = charIterator.getBeginIndex();
paragraphEnd = charIterator.getEndIndex();
lineMeasurer = new LineBreakMeasurer(charIterator, frc);

// Set break width to width of Component.
breakWidth = myTextWidth;
drawPosY = startY
// Set position to the index of the first character in the paragraph.
lineMeasurer.setPosition(paragraphStart);
textBounds = new Rectangle(startX, startY(), 0, 0);

// Get lines from until the entire paragraph has been displayed.
while (lineMeasurer.getPosition() < paragraphEnd) {

     layout = lineMeasurer.nextLayout(breakWidth);

     // Compute pen x position. If the paragraph is right-to-left we
     // will align the TextLayouts to the right edge of the panel.
     drawPosX = layout.isLeftToRight()
                    ? startX() : breakWidth - layout.getAdvance();

     // Draw the TextLayout at (drawPosX, drawPosY).
     layout.draw(g2d, drawPosX, drawPosY);
     lineBounds = new Rectangle2D.Float(drawPosX, drawPosY - layout.getAscent(), layout.getAdvance(), (layout.getAscent() + layout.getDescent() + layout.getLeading()));

     // Move y-coordinate in preparation for next layout.
     drawPosY += layout.getAscent() + layout.getDescent() + layout.getLeading();
}

JTextArea намного проще:

JTextArea textArea = new JTextArea(myText);
textArea.setSize(myTextWidth, myTextThing.getHeight());
textArea.setOpaque(true);
textArea.setVisible(true);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setFont(myFont);
textArea.setBorder(null);

Я установил границу на ноль, потому что у меня нарисован еще один прямоугольник за пределами текстовой области с пунктирной областью, чтобы показать, где он находится. Сейчас это может показаться глупым, но мы используем его для отображения границ текстовой области, когда пользователь впервые выбирает текст, который он хочет редактировать. На данный момент JTextArea еще не создан. Они должны нажать на нее еще раз, чтобы начать редактирование. Причина этого заключается в том, что после выделения текстовой области они также могут перетаскивать и изменять ее размер, и это становится беспорядочным и более запутанным, если у них была активная JTextArea, когда они начали перетаскивать и изменять ее размер.

Отдельно как нарисованные TextLayouts, так и JTextArea, по-видимому, прекрасно переносят слова. но при совместном использовании вы можете увидеть разницу. Проблема в том, что пока пользователь редактирует текст, JTextArea делает все возможное, чтобы обернуть текст. Но когда пользователь JTextArea теряет фокус, он преобразуется в нарисованный текст, и тогда слова могут быть перенесены по-разному.

1 Ответ

0 голосов
/ 04 апреля 2011

Заполните текстовую область символами i или l.Возьмите линейку пользовательского интерфейса или увеличительное стекло и подсчитайте размер текстовой области в пикселях от крайнего левого символа самой длинной строки до самого правого.Сделайте то же самое с n, m и несколькими другими символами, чтобы получить еще несколько точек данных.Я подозреваю, что текстовая область имеет невидимую границу в несколько пикселей, которую она использует, даже если она не имеет границы.Если это так, добавьте одну и ту же рамку вокруг компонента TextLayout, и они должны выглядеть одинаково.

(В качестве альтернативы подсчету пикселей можно установить цвет фона для текста или компонентов, но я бы не сталобязательно верь.)

...