Spec-Zone .ru
спецификации, руководства, описания, API
|
Этот раздел обсуждает, как работать с двунаправленным текстом с классами в java.awt
и java.awt.font
Следующие темы затрагиваются:
Если Вы планируете работать с компонентами Swing, см.
SE Java хранит текст в памяти в логическом порядке, который является порядком, в котором символы и слова читаются и пишутся. Логический порядок является не обязательно тем же самым как визуальным порядком, который является порядком, в котором выводятся на экран соответствующие глифы.
Система письменности' визуальный порядок должна сохраняться в двунаправленном тексте, даже когда языки смешиваются вместе. Это иллюстрируется в следующем числе, которое выводит на экран арабскую фразу, встроенную в английское предложение.
Отметьте: В этом и последующих примерах, арабский и еврейский текст представляется прописными буквами, и пробелы представляются подчеркиваниями. Каждая иллюстрация содержит две части: представление символов, сохраненных в памяти (символы в логическом порядке) сопровождаемый представлением того, как те символы выводятся на экран (символы в визуальном порядке). Числа ниже символьных полей указывают на смещения вставки.
Даже при том, что они - часть английского предложения, арабские слова выводятся на экран в арабском порядке сценария, справа налево. Поскольку курсивное арабское слово логически после арабского языка в простом тексте это визуально налево от простого текста.
Когда строка со смесью слева направо и справа налево текст выводится на экран, основное направление существенное. Основное направление является порядком сценария преобладающей системы письменности. Например, если текст является прежде всего английским с некоторым встроенным арабским языком, то основное направление слева направо. Если текст является прежде всего арабским с некоторым встроенным английским языком или числами, то основное направление справа налево.
Основное направление определяет порядок, в котором выводятся на экран сегменты текста с общим направлением. В примере, показанном в предыдущем числе, основное направление слева направо. В этом примере есть три направленных выполнения: английский текст в начале предложения работает слева направо, арабские текстовые выполнения справа налево, и выполнения периода слева направо.
Графика часто встраивается в поток текста. Эта встроенная графика ведет себя как глифы с точки зрения того, как они влияют на текстовый поток и обертывание строки. Такая встроенная графическая потребность, которая будет расположена, используя тот же самый двунаправленный алгоритм компоновки так, чтобы они появились в надлежащем расположении в потоке символов.
SE Java использует Unicode Двунаправленный Алгоритм, который является алгоритмом, который используется, чтобы упорядочить глифов в пределах строки, таким образом определяя направленность двунаправленных текстов. В большинстве случаев Вы не должны включать дополнительную информацию для этого алгоритма, чтобы получить корректное упорядочивание дисплея.
Чтобы позволить пользователю редактировать двунаправленный текст, следует быть в состоянии сделать следующее:
В доступном для редактирования тексте каре используется, чтобы графически представить текущую точку вставки, позицию в тексте, где новые символы будут вставлены. Как правило, каре показывают как мигающая вертикальная панель между двумя глифами. Новые символы вставляются и выводятся на экран в расположении каре.
Вычисление позиции каре может быть усложнено, особенно для двунаправленного текста. У смещений вставки на направленных границах есть две возможных позиции каре, потому что два глифа, которые соответствуют символьному смещению, не выводятся на экран смежные с друг другом. Это иллюстрируется в следующем числе. В этом числе каре, как показывают, как квадратные скобки указывают на глифа, которому соответствует каре.
Символ смещал 8, соответствует расположению после подчеркивания и перед A. Если пользователь вводит арабский символ, его глиф выводится на экран направо от (перед) A; если пользователь вводит английский символ, его глиф выводится на экран направо от (после) подчеркивания.
Чтобы обработать эту ситуацию, некоторые системы выводят на экран двойные каре, strong (основное) каре и слабое (вторичное) каре. Каре strong указывает, где вставленный символ будет выведен на экран, когда направление того символа будет тем же самым как основным направлением текста. Слабое каре показывает, где вставленный символ будет выведен на экран, когда направление символа будет противоположностью основного направления TextLayout
Когда Вы работаете с двунаправленным текстом, невозможно просто добавить ширины глифов перед символьным смещением, чтобы вычислить позицию каре. Если бы Вы сделали, то каре было бы оттянуто в неправильном месте, как показано в следующем числе:
Для каре, которое будет должным образом расположено, ширины глифов налево от смещения должны быть добавлены и текущий принятый во внимание контекст. Если контекст не будет принят во внимание, метрики глифа будут не обязательно соответствовать дисплей. (Контекст может влиять, какие глифы используются.)
Все текстовые редакторы позволяют пользователю перемещать каре с клавишами со стрелками. Пользователи ожидают, что каре переместится в направлении нажатой клавиши со стрелкой. В слева направо тексте, перемещая смещение вставки просто: клавиша со стрелкой вправо увеличивает вставку, смещенную одним, и клавиша со стрелкой влево уменьшает это одним. В двунаправленном тексте или в тексте с лигатурами, это поведение заставило бы каре переходить через глифов на границах направления и перемещаться в обратное направление в пределах различных направленных выполнений.
Чтобы переместить каре гладко через двунаправленный текст, Вы должны принять во внимание направление текстовых выполнений. Невозможно просто постепенно увеличить смещение вставки, когда клавиша со стрелкой вправо нажимается, и постепенно уменьшите это, когда клавиша со стрелкой влево нажимается. Если текущее смещение вставки в пределах выполнения справа налево символов, клавиша со стрелкой вправо должна уменьшить смещение вставки, и клавиша со стрелкой влево должна увеличить это.
Перемещение каре через направленную границу еще более усложняется. Следующее число иллюстрирует то, что происходит, когда направленная граница пересекается, когда пользователь перемещается с клавишей со стрелкой. Ступая три позиции направо в выведенный на экран текст соответствует перемещению в смещения символа 7, 19, тогда 18.
У определенных глифов никогда не должно быть каре между ними; вместо этого, каре должно переместиться как если бы глифы, представленные единственный символ. Например, никогда не должно быть каре между o и умляутом, если они представляются двумя отдельными символами.
TextLayout
getNextRightHit
getNextLeftHit
Часто, расположение в пространстве устройства должно быть преобразовано в текстовое смещение. Например, когда пользователь щелкает мышью по выбираемому тексту, расположение мыши преобразовывается в текстовое смещение и используется в качестве одного конца диапазона выбора. Логически, это - инверсия расположения каре.
Когда Вы работаете с двунаправленным текстом, единственное визуальное расположение в дисплее может соответствовать двум различным смещениям в исходном тексте, как показано в следующем числе:
Поскольку единственное визуальное расположение может соответствовать двум различным смещениям, совершить нападки, двунаправленный текст тестирования не является только вопросом измеряющихся ширин глифа, пока глиф в корректном расположении не находится и затем отображение что позиция назад к символьному смещению. Обнаружение стороны, что хит шел, помогает различить эти две альтернативы.
Можно выполнить использование тестирования хита TextLayout.hitTestChar
TextHitInfo
Выбранный диапазон символов представляется графически областью выделения, областью, в которой глифы выводятся на экран с инвертированным видеоизображением или против различного цвета фона.
Выделите области, как каре, более усложняются для двунаправленного текста чем для однонаправленного текста. В двунаправленном тексте у непрерывного диапазона символов не могло бы быть непрерывной области выделения когда выведено на экран. Наоборот, область выделения, показывая визуально непрерывный диапазон глифов не могла бы соответствовать единственному, непрерывному диапазону символов.
Это приводит к двум стратегиям выделения выборов в двунаправленном тексте:
Логическое выделение: С логическим выделением выбранные символы всегда непрерывны в текстовой модели, и области выделения позволяют быть несмежной. Следующее является примером логического выделения:
Визуальное выделение: С визуальным выделением мог бы быть больше чем один диапазон выбранных символов, но область выделения всегда непрерывна. Следующее является примером визуального выделения:
Логическое выделение более просто реализовать, так как выбранные символы всегда непрерывны в тексте.
Выборка
демонстрирует логическое выделение:SelectionSample.java
В зависимости от которых API Java Вы используете, у Вас могут быть так немного или такое большое управление текстовым расположением, как Вы нуждаетесь:
Если Вы только хотите вывести на экран блок текста или нуждаться в доступном для редактирования текстовом управлении, можно использовать JTextComponent
, который выполнит текстовое расположение для Вас. JTextComponent
JTextComponent
Если Вы хотите вывести на экран простую текстовую строку, можно вызвать метод Graphics2D.drawString
и позвольте 2-D Java, размечают строку для Вас. Можно также использовать Graphics2D.drawString
Graphics2D
Если Вы хотите реализовать свои собственные подпрограммы редактирования текста, можно использовать TextLayout
управлять текстовым расположением, выделением, и поражать обнаружение. Услуги, предоставленные TextLayout
Если Вы хотите полный контроль по тому, как текст формируется и располагается, можно создать свое собственное GlyphVector
Font
Graphics2D
Обычно, Вы не должны выполнить текстовые операции расположения самостоятельно. Для большинства приложений, JTextComponent
JTextComponent
TextLayout
TextLayout
TextLayout
TextLayout
TextLayout
TextLayout
TextLayout
TextLayout
TextLayout
TextLayout
TextLayout
LineBreakMeasurer
Основное направление текста обычно устанавливается атрибутом (стиль) на тексте. Если тот атрибут отсутствует, TextLayout
следует за Unicode двунаправленный алгоритм и получает основное направление из начальных символов в абзаце.
TextLayout
Shape
TextLayout
TextLayout
Shapes
и автоматически поддерживает двойные каре. Для курсива и наклонных глифов, TextLayout
Учитывая смещение вставки, getCaretShapes
Shape
Shape
Если Вы хотите использовать пользовательские каре, можно получить позицию и угол каре от TextLayout
Выборка
демонстрирует двойные каре.HitTestSample.java
Щелчок по o на стороне o к еврейским текстовым записям, что конечный пользователь, по которому щелкают после o, который является частью английского текста. Это располагает слабое (черное) каре рядом с o и каре strong (красное) перед H:
Щелчок по пространству направо от записей o, что конечный пользователь, по которому щелкают пространство, которое является частью еврейского текста. Это располагает strong (красное) каре рядом с o и слабое каре (черное) перед H:
Можно также использовать TextLayout
class, чтобы определить получающееся смещение вставки, когда пользователь нажимает левую или правую клавишу со стрелкой. Данный a TextHitInfo
объект, который представляет текущее смещение вставки, getNextRightHit
TextHitInfo
getNextLeftHit
Следующая выборка от выборки
демонстрирует, как определить получающееся смещение вставки, когда пользователь нажимает левую или правую клавишу со стрелкой:ArrowKeySample.java
public class ArrowKeySample extends JPanel implements KeyListener { // ... private static void createAndShowGUI() { // Create and set up the window. ArrowKey demo = new ArrowKey(); frame = new JFrame("Arrow Key Sample"); frame.addKeyListener(demo); // ... } private void handleArrowKey(boolean rightArrow) { TextHitInfo newPosition; if (rightArrow) { newPosition = textLayout.getNextRightHit(insertionIndex); } else { newPosition = textLayout.getNextLeftHit(insertionIndex); } // getNextRightHit() / getNextLeftHit() will return null if // there is not a caret position to the right (left) of the // current position. if (newPosition != null) { // Update insertionIndex. insertionIndex = newPosition.getInsertionIndex(); // Repaint the Component so the new caret(s) will be displayed. frame.repaint(); } } // ... @Override public void keyPressed(KeyEvent e) { int keyCode = e.getKeyCode(); if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT) { handleArrowKey(keyCode == KeyEvent.VK_RIGHT); } } }
TextLayout
class обеспечивает простой механизм для текста тестирования хита. hitTextChar
TextHitInfo
TextHitInfo
Следующая выборка от
получает смещение от щелчка мышью:HitTestSample.java
private class HitTestMouseListener extends MouseAdapter { public void mouseClicked(MouseEvent e) { Point2D origin = computeLayoutOrigin(); // Compute the mouse click location relative to // textLayout's origin. float clickX = (float) (e.getX() - origin.getX()); float clickY = (float) (e.getY() - origin.getY()); // Get the character position of the mouse click. TextHitInfo currentHit = textLayout.hitTestChar(clickX, clickY); insertionIndex = currentHit.getInsertionIndex(); // Repaint the Component so the new caret(s) will be displayed. repaint(); } }
Можно получить a Shape
это представляет область выделения от TextLayout
TextLayout
TextLayout
Следующая выборка от
демонстрирует один способ вывести на экран выделенный текст:SelectionSample.java
public void paint(Graphics g) { // ... boolean haveCaret = anchorEnd == activeEnd; if (!haveCaret) { // Retrieve highlight region for selection range. Shape highlight = textLayout.getLogicalHighlightShape(anchorEnd, activeEnd); // Fill the highlight region with the highlight color. graphics2D.setColor(HIGHLIGHT_COLOR); graphics2D.fill(highlight); } // ... } // ... private class SelectionMouseMotionListener extends MouseMotionAdapter { public void mouseDragged(MouseEvent e) { Point2D origin = computeLayoutOrigin(); // Compute the mouse location relative to // textLayout's origin. float clickX = (float) (e.getX() - origin.getX()); float clickY = (float) (e.getY() - origin.getY()); // Get the character position of the mouse location. TextHitInfo position = textLayout.hitTestChar(clickX, clickY); int newActiveEnd = position.getInsertionIndex(); // If newActiveEnd is different from activeEnd, update activeEnd // and repaint the Panel so the new selection will be displayed. if (activeEnd != newActiveEnd) { activeEnd = newActiveEnd; frame.repaint(); } } } private class SelectionMouseListener extends MouseAdapter { public void mousePressed(MouseEvent e) { Point2D origin = computeLayoutOrigin(); // Compute the mouse location relative to // TextLayout's origin. float clickX = (float) (e.getX() - origin.getX()); float clickY = (float) (e.getY() - origin.getY()); // Set the anchor and active ends of the selection // to the character position of the mouse location. TextHitInfo position = textLayout.hitTestChar(clickX, clickY); anchorEnd = position.getInsertionIndex(); activeEnd = anchorEnd; // Repaint the Panel so the new selection will be displayed. frame.repaint(); } }
Метод SelectionMouseListener.mousePressed
определяет переменную anchorEnd
, который является позицией в тексте, где мышью щелкнули. Метод SelectionMouseMotionListener.mouseDragged
определяет переменную activeEnd
, который является позицией в тексте туда, где мышь была перетащена. paint
метод получает a Shape
объект, который представляет выбранный текст (текст между позициями anchorEnd
и activeEnd
). paint
метод тогда заполняется Shape