绘制多行文本

原文: https://docs.oracle.com/javase/tutorial/2d/text/drawmulstring.html

如果您想要在特定宽度内放置一段样式文本,则可以使用LineBreakMeasurer类。此类使样式化文本可以分成行,以便它们适合特定的视觉前进。每行作为TextLayout对象返回,该对象表示不可更改的样式字符数据。但是,此类还允许访问布局信息。 TextLayoutgetAscentgetDescent方法返回有关用于定位组件中的线的字体的信息。文本存储为AttributedCharacterIterator对象,以便字体和磅值属性可以与文本一起存储。

以下 applet 使用LineBreakMeasurerTextLayoutAttributedCharacterIterator在一个组件中定位一段样式文本。

<applet alt=”LineBreakSample applet” archive=”examples/lib/LineBreakSampleApplet.jar” code=”LineBreakSample” height=”250” width=”400”><param name=”permissions” value=”sandbox”></applet>


Note: If you don’t see the applet running, you need to install at least the Java SE Development Kit (JDK) 7 release.


该 applet 的完整代码位于 LineBreakSample.java中。

以下代码使用字符串vanGogh创建一个迭代器。检索迭代器的开始和结束,并从迭代器创建一个新的LineBreakMeasurer

  1. AttributedCharacterIterator paragraph = vanGogh.getIterator();
  2. paragraphStart = paragraph.getBeginIndex();
  3. paragraphEnd = paragraph.getEndIndex();
  4. FontRenderContext frc = g2d.getFontRenderContext();
  5. lineMeasurer = new LineBreakMeasurer(paragraph, frc);

窗口的大小用于确定线应该断开的位置。此外,还为段落中的每一行创建了TextLayout对象。

  1. // Set break width to width of Component.
  2. float breakWidth = (float)getSize().width;
  3. float drawPosY = 0;
  4. // Set position to the index of the first
  5. // character in the paragraph.
  6. lineMeasurer.setPosition(paragraphStart);
  7. // Get lines from until the entire paragraph
  8. // has been displayed.
  9. while (lineMeasurer.getPosition() < paragraphEnd) {
  10. TextLayout layout = lineMeasurer.nextLayout(breakWidth);
  11. // Compute pen x position. If the paragraph
  12. // is right-to-left we will align the
  13. // TextLayouts to the right edge of the panel.
  14. float drawPosX = layout.isLeftToRight()
  15. ? 0 : breakWidth - layout.getAdvance();
  16. // Move y-coordinate by the ascent of the
  17. // layout.
  18. drawPosY += layout.getAscent();
  19. // Draw the TextLayout at (drawPosX,drawPosY).
  20. layout.draw(g2d, drawPosX, drawPosY);
  21. // Move y-coordinate in preparation for next
  22. // layout.
  23. drawPosY += layout.getDescent() + layout.getLeading();
  24. }

TextLayout类不经常由应用程序直接创建。但是,当应用程序需要直接处理在文本中的特定位置应用了样式(文本属性)的文本时,此类很有用。例如,要在段落中绘制一个单词斜体,应用程序需要执行测量并为每个子字符串设置字体。如果文本是双向的,则此任务不容易正确执行。从AttributedString对象创建TextLayout对象会为您解决此问题。有关 TextLayout 的更多信息,请参阅 Java SE 规范。