- java.lang.Object
-
- java.awt.font.LineBreakMeasurer
-
public final class LineBreakMeasurer extends Object
LineBreakMeasurer
类允许将样式化文本分解为适合特定视觉前进的行(或段)。 这对于希望显示适合特定宽度的文本段落(称为包装宽度)的客户非常有用。LineBreakMeasurer
使用样式文本上的迭代器构造。 迭代器的范围应该是文本中的单个段落。LineBreakMeasurer
在文本中保留下一个文本段开头的位置。 最初,这个位置是文本的开头。 根据双向格式规则为段落分配总体方向(从左到右或从右到左)。 从段落中获得的所有段都与段落具有相同的方向。通过调用方法
nextLayout
获得文本段,该方法返回表示适合包裹宽度的文本的TextLayout
。nextLayout
方法将当前位置移动到从nextLayout
返回的布局的nextLayout
。LineBreakMeasurer
实现了最常用的换行策略:适合包装宽度的每个单词都放在行上。 如果第一个单词不适合,那么适合包装宽度的所有字符都放在该行上。 每行至少放置一个字符。该
TextLayout
情况下,通过返回LineBreakMeasurer
对待标签如0角空格。 希望获得制表符分隔的定位段的客户端应使用nextLayout
的重载,该过载在nextLayout
中采用限制偏移量。 限制偏移量应该是选项卡后面的第一个字符。 从此方法返回的TextLayout
对象以提供的限制结束(或者之前,如果当前位置和限制之间的文本不完全适合包装宽度)。在将第一个段放置在一条线上之后,正在布置制表符分隔文本的客户端需要稍微不同的换行策略。 它们不应该在剩余空间中拟合部分单词,而应将完全不适合剩余空间的单词放在下一行。 可以在
nextLayout
的超载中请求此策略更改,该参数采用boolean
参数。 如果此参数为true
,则如果第一个单词不适合给定空间,则nextLayout
将返回null
。 请参阅下面的选项卡示例。通常,如果用于构造
LineBreakMeasurer
的文本发生更改,LineBreakMeasurer
必须构造新的LineBreakMeasurer
以反映更改。 (旧的LineBreakMeasurer
继续正常运行,但它不会知道文本更改。)尽管如此,如果文本更改是插入或删除单个字符,LineBreakMeasurer
可以通过调用insertChar
或更新现有的insertChar
或deleteChar
。 更新现有的LineBreakMeasurer
比创建新的快得多。 根据用户输入修改文本的客户端应该利用这些方法。示例 :
在组件中呈现段落
public void paint(Graphics graphics) { float dx = 0f, dy = 5f; Graphics2D g2d = (Graphics2D)graphics; FontRenderContext frc = g2d.getFontRenderContext(); AttributedString text = new AttributedString("....."); AttributedCharacterIterator paragraph = text.getIterator(); LineBreakMeasurer measurer = new LineBreakMeasurer(paragraph, frc); measurer.setPosition(paragraph.getBeginIndex()); float wrappingWidth = (float)getSize().width; while (measurer.getPosition() < paragraph.getEndIndex()) { TextLayout layout = measurer.nextLayout(wrappingWidth); dy += (layout.getAscent()); float dx = layout.isLeftToRight() ? 0 : (wrappingWidth - layout.getAdvance()); layout.draw(graphics, dx, dy); dy += layout.getDescent() + layout.getLeading(); } }
使用选项卡呈现文本。 为简单起见,假设整个文本方向是从左到右
public void paint(Graphics graphics) { float leftMargin = 10, rightMargin = 310; float[] tabStops = { 100, 250 }; // assume styledText is an AttributedCharacterIterator, and the number // of tabs in styledText is tabCount int[] tabLocations = new int[tabCount+1]; int i = 0; for (char c = styledText.first(); c != styledText.DONE; c = styledText.next()) { if (c == '\t') { tabLocations[i++] = styledText.getIndex(); } } tabLocations[tabCount] = styledText.getEndIndex() - 1; // Now tabLocations has an entry for every tab's offset in // the text. For convenience, the last entry is tabLocations // is the offset of the last character in the text. LineBreakMeasurer measurer = new LineBreakMeasurer(styledText); int currentTab = 0; float verticalPos = 20; while (measurer.getPosition() < styledText.getEndIndex()) { // Lay out and draw each line. All segments on a line // must be computed before any drawing can occur, since // we must know the largest ascent on the line. // TextLayouts are computed and stored in a Vector; // their horizontal positions are stored in a parallel // Vector. // lineContainsText is true after first segment is drawn boolean lineContainsText = false; boolean lineComplete = false; float maxAscent = 0, maxDescent = 0; float horizontalPos = leftMargin; Vector layouts = new Vector(1); Vector penPositions = new Vector(1); while (!lineComplete) { float wrappingWidth = rightMargin - horizontalPos; TextLayout layout = measurer.nextLayout(wrappingWidth, tabLocations[currentTab]+1, lineContainsText); // layout can be null if lineContainsText is true if (layout != null) { layouts.addElement(layout); penPositions.addElement(new Float(horizontalPos)); horizontalPos += layout.getAdvance(); maxAscent = Math.max(maxAscent, layout.getAscent()); maxDescent = Math.max(maxDescent, layout.getDescent() + layout.getLeading()); } else { lineComplete = true; } lineContainsText = true; if (measurer.getPosition() == tabLocations[currentTab]+1) { currentTab++; } if (measurer.getPosition() == styledText.getEndIndex()) lineComplete = true; else if (horizontalPos >= tabStops[tabStops.length-1]) lineComplete = true; if (!lineComplete) { // move to next tab stop int j; for (j=0; horizontalPos >= tabStops[j]; j++) {} horizontalPos = tabStops[j]; } } verticalPos += maxAscent; Enumeration layoutEnum = layouts.elements(); Enumeration positionEnum = penPositions.elements(); // now iterate through layouts and draw them while (layoutEnum.hasMoreElements()) { TextLayout nextLayout = (TextLayout) layoutEnum.nextElement(); Float nextPosition = (Float) positionEnum.nextElement(); nextLayout.draw(graphics, nextPosition.floatValue(), verticalPos); } verticalPos += maxDescent; } }
- 另请参见:
-
TextLayout
-
-
构造方法摘要
构造方法 构造器 描述 LineBreakMeasurer(AttributedCharacterIterator text, FontRenderContext frc)
为指定的文本构造一个LineBreakMeasurer
。LineBreakMeasurer(AttributedCharacterIterator text, BreakIterator breakIter, FontRenderContext frc)
为指定的文本构造一个LineBreakMeasurer
。
-
方法摘要
所有方法 实例方法 具体的方法 变量和类型 方法 描述 void
deleteChar(AttributedCharacterIterator newParagraph, int deletePos)
从文本中删除单个字符后更新此LineBreakMeasurer
,并将当前位置设置为段落的开头。int
getPosition()
返回此LineBreakMeasurer
的当前位置。void
insertChar(AttributedCharacterIterator newParagraph, int insertPos)
在将单个字符插入文本后更新此LineBreakMeasurer
,并将当前位置设置为段落的开头。TextLayout
nextLayout(float wrappingWidth)
返回下一个布局,并更新当前位置。TextLayout
nextLayout(float wrappingWidth, int offsetLimit, boolean requireNextWord)
返回下一个布局,并更新当前位置。int
nextOffset(float wrappingWidth)
返回下一个布局末尾的位置。int
nextOffset(float wrappingWidth, int offsetLimit, boolean requireNextWord)
返回下一个布局末尾的位置。void
setPosition(int newPosition)
设置此LineBreakMeasurer
的当前位置。
-
-
-
构造方法详细信息
-
LineBreakMeasurer
public LineBreakMeasurer(AttributedCharacterIterator text, FontRenderContext frc)
为指定的文本构造一个LineBreakMeasurer
。- 参数
-
text
- 此LineBreakMeasurer
生成TextLayout
对象的文本; 文本必须至少包含一个字符; 如果通过iter
提供的文本发生更改,则对此LineBreakMeasurer
实例的进一步调用未定义(在某些情况下,以后调用insertChar
或deleteChar
时 - 请参见下文) -
frc
- 包含有关正确测量文本所需的图形设备的信息; 文本测量值可能会略有不同,具体取决于设备分辨率和抗锯齿等属性; 此参数未指定LineBreakMeasurer
与用户空间之间的LineBreakMeasurer
- 另请参见:
-
insertChar(java.text.AttributedCharacterIterator, int)
,deleteChar(java.text.AttributedCharacterIterator, int)
-
LineBreakMeasurer
public LineBreakMeasurer(AttributedCharacterIterator text, BreakIterator breakIter, FontRenderContext frc)
为指定的文本构造一个LineBreakMeasurer
。- 参数
-
text
- 此LineBreakMeasurer
生成TextLayout
对象的文本; 文本必须至少包含一个字符; 如果通过iter
提供的文本发生更改,则对此LineBreakMeasurer
实例的进一步调用未定义(在某些情况下,之后调用insertChar
或deleteChar
时 - 请参见下文) -
breakIter
- 定义换行符的BreakIterator
-
frc
- 包含有关正确测量文本所需的图形设备的信息; 文本测量值可能会略有不同,具体取决于设备分辨率和抗锯齿等属性; 此参数未指定LineBreakMeasurer
与用户空间之间的LineBreakMeasurer
- 异常
-
IllegalArgumentException
- 如果文本少于一个字符 - 另请参见:
-
insertChar(java.text.AttributedCharacterIterator, int)
,deleteChar(java.text.AttributedCharacterIterator, int)
-
-
方法详细信息
-
nextOffset
public int nextOffset(float wrappingWidth)
返回下一个布局末尾的位置。 不更新此LineBreakMeasurer
的当前位置。- 参数
-
wrappingWidth
- 下一个布局中文本允许的最大可见提前量 - 结果
-
表示下一个
TextLayout
限制的文本中的偏移量。
-
nextOffset
public int nextOffset(float wrappingWidth, int offsetLimit, boolean requireNextWord)
返回下一个布局末尾的位置。 不更新此LineBreakMeasurer
的当前位置。- 参数
-
wrappingWidth
- 下一个布局中文本允许的最大可见提前量 -
offsetLimit
- 第一个不能包含在下一个布局中的字符,即使限制后的文本适合包装宽度;offsetLimit
必须大于当前位置 -
requireNextWord
- 如果是true
,则当整个下一个单词不适合wrappingWidth
返回的当前位置; 如果是false
,则返回的偏移量至少比当前位置大1 - 结果
-
表示下一个
TextLayout
限制的文本中的偏移量
-
nextLayout
public TextLayout nextLayout(float wrappingWidth)
返回下一个布局,并更新当前位置。- 参数
-
wrappingWidth
- 下一个布局中文本允许的最大可见提前量 - 结果
-
a
TextLayout
,从当前位置开始,代表wrappingWidth
内的下一行
-
nextLayout
public TextLayout nextLayout(float wrappingWidth, int offsetLimit, boolean requireNextWord)
返回下一个布局,并更新当前位置。- 参数
-
wrappingWidth
- 下一个布局中文本允许的最大可见提前量 -
offsetLimit
- 第一个不能包含在下一个布局中的字符,即使限制后的文本适合包装宽度;offsetLimit
必须大于当前位置 -
requireNextWord
- 如果是true
,并且如果当前位置的整个单词不适合包装宽度,则返回null
。 如果是false
,则返回有效布局,该布局至少包括当前位置的字符 - 结果
-
a
TextLayout
,从当前位置开始,代表wrappingWidth
内的下一行。 如果当前位置位于此LineBreakMeasurer
使用的文本的LineBreakMeasurer
,则返回null
-
getPosition
public int getPosition()
返回此LineBreakMeasurer
的当前位置。- 结果
-
这个
LineBreakMeasurer
的当前位置 - 另请参见:
-
setPosition(int)
-
setPosition
public void setPosition(int newPosition)
设置此LineBreakMeasurer
的当前位置。- 参数
-
newPosition
- 这个当前位置LineBreakMeasurer
; 该位置应在用于构造此LineBreakMeasurer
的文本内(或在最近传递给insertChar
或deleteChar
- 另请参见:
-
getPosition()
-
insertChar
public void insertChar(AttributedCharacterIterator newParagraph, int insertPos)
在将单个字符插入文本后更新此LineBreakMeasurer
,并将当前位置设置为段落的开头。- 参数
-
newParagraph
- 插入后的文本 -
insertPos
- 文本中插入字符的位置 - 异常
-
IndexOutOfBoundsException
- 如果insertPos
小于newParagraph
或大于或等于newParagraph
-
NullPointerException
- 如果newParagraph
是null
- 另请参见:
-
deleteChar(java.text.AttributedCharacterIterator, int)
-
deleteChar
public void deleteChar(AttributedCharacterIterator newParagraph, int deletePos)
从文本中删除单个字符后更新此LineBreakMeasurer
,并将当前位置设置为段落的开头。- 参数
-
newParagraph
- 删除后的文本 -
deletePos
- 删除字符的文本中的位置 - 异常
-
IndexOutOfBoundsException
-如果deletePos
小于开始newParagraph
或大于的端newParagraph
-
NullPointerException
- 如果newParagraph
是null
- 另请参见:
-
insertChar(java.text.AttributedCharacterIterator, int)
-
-