Класс LineBreakMeasurer
public final class LineBreakMeasurer extends Object
LineBreakMeasurer позволяет разбивать форматированный текст на строки (или сегменты), которые помещаются в определённую область. Это полезно для клиентов, которые хотят отобразить абзац текста, который помещается в определённую ширину, называемую шириной обрыва. LineBreakMeasurer создаётся с итератором по форматированному тексту. Диапазон итератора должен охватывать один абзац в тексте. LineBreakMeasurer сохраняет позицию в тексте для начала следующего сегмента текста. Изначально эта позиция — начало текста. Абзацам назначается общее направление (слева направо или справа налево) в соответствии с правилами двунаправленного форматирования. Все сегменты, полученные из абзаца, имеют то же направление, что и сам абзац.
Сегменты текста получаются вызовом метода nextLayout, который возвращает TextLayout, представляющий текст, который помещается в ширину обрыва. Метод nextLayout перемещает текущую позицию в конец макета, возвращённого методом nextLayout.
LineBreakMeasurer реализует наиболее часто используемую политику разделения на строки: каждое слово, которое помещается в ширину обрыва, размещается на строке. Если первое слово не помещается, то все символы, которые помещаются в ширину обрыва, размещаются на строке. На каждой строке размещается хотя бы один символ.
Экземпляры TextLayout , возвращаемые методом LineBreakMeasurer , обрабатывают табуляции как пробелы нулевой ширины. Клиенты, которые хотят получить сегменты с табуляцией для позиционирования, должны использовать перегрузку метода nextLayout, принимающую ограничивающий смещение в тексте. Ограничивающее смещение должно быть первым символом после табуляции. Объекты TextLayout , возвращаемые этим методом, заканчиваются на предоставленном ограничении (или раньше, если текст между текущей позицией и ограничением не полностью помещается в ширину обрыва).
Клиентам, выстраивающим текст с табуляцией, нужна немного другая политика разделения на строки после того, как первый сегмент был размещён на строке. Вместо того, чтобы размещать части слов в оставшемся пространстве, они должны размещать слова, которые не помещаются в оставшемся пространстве, полностью на следующей строке. Это изменение политики можно запросить в перегрузке метода nextLayout , принимающей параметр boolean. Если этот параметр равен true, метод nextLayout возвращает null , если первое слово не помещается в заданное пространство. См. пример с табуляцией ниже.
В общем случае, если текст, используемый для создания экземпляра LineBreakMeasurer , меняется, необходимо создать новый экземпляр LineBreakMeasurer , чтобы отразить изменения. (Старый экземпляр LineBreakMeasurer продолжает работать корректно, но не будет знать об изменении текста.) Тем не менее, если изменение текста заключается в вставке или удалении одного символа, существующий экземпляр LineBreakMeasurer можно «обновить», вызвав методы 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; } }
- См. также:
Краткое описание конструкторов
| Конструктор | Описание |
|---|---|
LineBreakMeasurer |
Создаёт экземпляр LineBreakMeasurer для указанного текста. |
LineBreakMeasurer |
Создаёт экземпляр LineBreakMeasurer для указанного текста. |
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
void |
deleteChar |
Обновляет этот экземпляр LineBreakMeasurer после удаления одного символа из текста и устанавливает текущую позицию в начало абзаца. |
int |
getPosition() |
Возвращает текущую позицию этого экземпляра LineBreakMeasurer. |
void |
insertChar |
Обновляет этот экземпляр LineBreakMeasurer после вставки одного символа в текст и устанавливает текущую позицию в начало абзаца. |
TextLayout |
nextLayout |
Возвращает следующий макет и обновляет текущую позицию. |
TextLayout |
nextLayout |
Возвращает следующий макет и обновляет текущую позицию. |
int |
nextOffset |
Возвращает позицию в конце следующего макета. |
int |
nextOffset |
Возвращает позицию в конце следующего макета. |
void |
setPosition |
Устанавливает текущую позицию этого экземпляра LineBreakMeasurer. |
Подробное описание конструкторов
LineBreakMeasurer
public LineBreakMeasurer(AttributedCharacterIterator text, FontRenderContext frc)
LineBreakMeasurer для указанного текста.- Параметры:
-
text- текст, для которого этотLineBreakMeasurerсоздаёт объектыTextLayout; текст должен содержать как минимум один символ; если текст, доступный черезiter, изменится, дальнейшие вызовы этого экземпляраLineBreakMeasurerбудут неопределёнными (за исключением некоторых случаев, когда вызываютсяinsertCharилиdeleteChar- см. ниже) -
frc- содержит информацию о графическом устройстве, необходимую для правильного измерения текста; измерения текста могут незначительно отличаться в зависимости от разрешения устройства и таких атрибутов, как сглаживание; этот параметр не определяет преобразование междуLineBreakMeasurerи пространством пользователя - См. также:
LineBreakMeasurer
public LineBreakMeasurer(AttributedCharacterIterator text, BreakIterator breakIter, FontRenderContext frc)
LineBreakMeasurer для указанного текста.- Параметры:
-
text- текст, для которого этотLineBreakMeasurerсоздаёт объектыTextLayout; текст должен содержать как минимум один символ; если текст, доступный черезiter, изменится, дальнейшие вызовы этого экземпляраLineBreakMeasurerбудут неопределёнными (за исключением некоторых случаев, когда вызываютсяinsertCharилиdeleteChar- см. ниже) -
breakIter-BreakIterator, определяющий разрывы строк -
frc- содержит информацию о графическом устройстве, необходимую для корректного измерения текста; измерения текста могут незначительно отличаться в зависимости от разрешения устройства и атрибутов, таких как сглаживание; этот параметр не задаёт преобразование междуLineBreakMeasurerи пространством пользователя - Исключения:
-
IllegalArgumentException- если текст содержит менее одного символа - См. также:
Подробное описание методов
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, возвращаемое смещение будет по крайней мере на единицу больше текущей позиции - Возвращает:
- смещение в тексте, представляющее границу следующей
TextLayout
nextLayout
public TextLayout nextLayout(float wrappingWidth)
- Параметры:
-
wrappingWidth- максимальное видимое смещение, разрешённое для текста в следующей компоновке - Возвращает:
TextLayout, начинающуюся с текущей позиции, которая представляет следующую строку, помещающуюся вwrappingWidth
nextLayout
public TextLayout nextLayout(float wrappingWidth, int offsetLimit, boolean requireNextWord)
- Параметры:
-
wrappingWidth- максимальное видимое смещение, разрешённое для текста в следующей компоновке -
offsetLimit- первый символ, который не может быть включён в следующую компоновку, даже если текст после предела поместится в ширину выравнивания;offsetLimitдолжно быть больше текущей позиции -
requireNextWord- еслиtrue, и если всё слово в текущей позиции не помещается в ширину выравнивания, возвращаетсяnull. Еслиfalse, возвращается корректная компоновка, включающая по крайней мере символ в текущей позиции - Возвращает:
TextLayout, начинающуюся с текущей позиции, которая представляет следующую строку, помещающуюся вwrappingWidth. Если текущая позиция находится в конце текста, используемого этимLineBreakMeasurer, возвращаетсяnull
getPosition
public int getPosition()
LineBreakMeasurer.- Возвращает:
- текущую позицию этого
LineBreakMeasurer - См. также:
setPosition
public void setPosition(int newPosition)
LineBreakMeasurer.- Параметры:
-
newPosition- текущая позиция этогоLineBreakMeasurer; позиция должна быть внутри текста, использованного для построения этогоLineBreakMeasurer(или в тексте, недавно переданном вinsertCharилиdeleteChar - См. также:
insertChar
public void insertChar(AttributedCharacterIterator newParagraph, int insertPos)
LineBreakMeasurer после вставки одного символа в текст и устанавливает текущую позицию в начало абзаца.- Параметры:
-
newParagraph- текст после вставки -
insertPos- позиция в тексте, в которую вставляется символ - Исключения:
-
IndexOutOfBoundsException- еслиinsertPosменьше началаnewParagraphили больше или равно концуnewParagraph -
NullPointerException- еслиnewParagraph-null - См. также:
deleteChar
public void deleteChar(AttributedCharacterIterator newParagraph, int deletePos)
LineBreakMeasurer после удаления одного символа из текста и устанавливает текущую позицию в начало абзаца.- Параметры:
-
newParagraph- текст после удаления -
deletePos- позиция в тексте, из которой удаляется символ - Исключения:
-
IndexOutOfBoundsException- еслиdeletePosменьше началаnewParagraphили больше концаnewParagraph -
NullPointerException- еслиnewParagraph-null - См. также:
© 1993, 2021, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/17/docs/api/java.desktop/java/awt/font/LineBreakMeasurer.html