Spec-Zone .ru
спецификации, руководства, описания, API
След: 2-D Графика
Урок: Работа с текстовыми API
Раздел: Усовершенствованный текстовый Дисплей
Работа с Двунаправленным текстом
Домашняя страница > 2-D Графика > Работа с текстовыми API

Работа с Двунаправленным текстом

Этот раздел обсуждает, как работать с двунаправленным текстом с классами в java.awt и java.awt.font пакеты. Эти классы, которым позволяют Вы потянуть разработанный текст на любом языке или сценарий, поддерживаемый Стандартом Unicode: глобальная система кодировки символов для того, чтобы обработать разнообразные современные, классические, и исторические языки. При рисовании текста направление, текст читается, должно быть принято во внимание так, чтобы все слова в строке вывели на экран правильно. Эти классы поддерживают направление текста, и правильно тянет это независимо от того, если строка работает слева направо, справа налево, или оба (двунаправленные). Двунаправленный текст представляет интересные проблемы для того, чтобы правильно расположить каре, точно определяя местоположение выборов, и правильно выводя на экран многократные строки. Также двунаправленный и справа налево текст представляют подобные проблемы для того, чтобы переместить каре в корректное направление в ответ на правые и левые нажатия клавиши со стрелкой.

Следующие темы затрагиваются:

Если Вы планируете работать с компонентами Swing, см. Работу с Двунаправленным текстом с Классом JTextComponent и Используя текстовые Компоненты для получения дополнительной информации.

Упорядочивание текста

SE Java хранит текст в памяти в логическом порядке, который является порядком, в котором символы и слова читаются и пишутся. Логический порядок является не обязательно тем же самым как визуальным порядком, который является порядком, в котором выводятся на экран соответствующие глифы.

Система письменности' визуальный порядок должна сохраняться в двунаправленном тексте, даже когда языки смешиваются вместе. Это иллюстрируется в следующем числе, которое выводит на экран арабскую фразу, встроенную в английское предложение.

Отметьте: В этом и последующих примерах, арабский и еврейский текст представляется прописными буквами, и пробелы представляются подчеркиваниями. Каждая иллюстрация содержит две части: представление символов, сохраненных в памяти (символы в логическом порядке) сопровождаемый представлением того, как те символы выводятся на экран (символы в визуальном порядке). Числа ниже символьных полей указывают на смещения вставки.

Арабская фраза встраивается в английское предложение

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

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

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

Графика часто встраивается в поток текста. Эта встроенная графика ведет себя как глифы с точки зрения того, как они влияют на текстовый поток и обертывание строки. Такая встроенная графическая потребность, которая будет расположена, используя тот же самый двунаправленный алгоритм компоновки так, чтобы они появились в надлежащем расположении в потоке символов.

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

Управление Двунаправленным текстом

Чтобы позволить пользователю редактировать двунаправленный текст, следует быть в состоянии сделать следующее:

Отображение Каре

В доступном для редактирования тексте каре используется, чтобы графически представить текущую точку вставки, позицию в тексте, где новые символы будут вставлены. Как правило, каре показывают как мигающая вертикальная панель между двумя глифами. Новые символы вставляются и выводятся на экран в расположении каре.

Вычисление позиции каре может быть усложнено, особенно для двунаправленного текста. У смещений вставки на направленных границах есть две возможных позиции каре, потому что два глифа, которые соответствуют символьному смещению, не выводятся на экран смежные с друг другом. Это иллюстрируется в следующем числе. В этом числе каре, как показывают, как квадратные скобки указывают на глифа, которому соответствует каре.

Двойные каре

Символ смещал 8, соответствует расположению после подчеркивания и перед A. Если пользователь вводит арабский символ, его глиф выводится на экран направо от (перед) A; если пользователь вводит английский символ, его глиф выводится на экран направо от (после) подчеркивания.

Чтобы обработать эту ситуацию, некоторые системы выводят на экран двойные каре, strong (основное) каре и слабое (вторичное) каре. Каре strong указывает, где вставленный символ будет выведен на экран, когда направление того символа будет тем же самым как основным направлением текста. Слабое каре показывает, где вставленный символ будет выведен на экран, когда направление символа будет противоположностью основного направления TextLayout автоматически поддерживает двойные каре.

Когда Вы работаете с двунаправленным текстом, невозможно просто добавить ширины глифов перед символьным смещением, чтобы вычислить позицию каре. Если бы Вы сделали, то каре было бы оттянуто в неправильном месте, как показано в следующем числе:

Каре, оттянутое неправильно

Для каре, которое будет должным образом расположено, ширины глифов налево от смещения должны быть добавлены и текущий принятый во внимание контекст. Если контекст не будет принят во внимание, метрики глифа будут не обязательно соответствовать дисплей. (Контекст может влиять, какие глифы используются.)

Перемещение Каре

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

Чтобы переместить каре гладко через двунаправленный текст, Вы должны принять во внимание направление текстовых выполнений. Невозможно просто постепенно увеличить смещение вставки, когда клавиша со стрелкой вправо нажимается, и постепенно уменьшите это, когда клавиша со стрелкой влево нажимается. Если текущее смещение вставки в пределах выполнения справа налево символов, клавиша со стрелкой вправо должна уменьшить смещение вставки, и клавиша со стрелкой влево должна увеличить это.

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

Перемещение каре

У определенных глифов никогда не должно быть каре между ними; вместо этого, каре должно переместиться как если бы глифы, представленные единственный символ. Например, никогда не должно быть каре между o и умляутом, если они представляются двумя отдельными символами.

TextLayout class обеспечивает методы ( getNextRightHit и getNextLeftHit) это позволяет Вам легко переместить каре гладко через двунаправленный текст.

Тестирование хита

Часто, расположение в пространстве устройства должно быть преобразовано в текстовое смещение. Например, когда пользователь щелкает мышью по выбираемому тексту, расположение мыши преобразовывается в текстовое смещение и используется в качестве одного конца диапазона выбора. Логически, это - инверсия расположения каре.

Когда Вы работаете с двунаправленным текстом, единственное визуальное расположение в дисплее может соответствовать двум различным смещениям в исходном тексте, как показано в следующем числе:

Хит, тестирующий двунаправленный текст

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

Можно выполнить использование тестирования хита TextLayout.hitTestChar. Информация о хите инкапсулируется в a TextHitInfo возразите и включает информацию о стороне, что хит шел.

Выделение Выборов

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

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

Это приводит к двум стратегиям выделения выборов в двунаправленном тексте:

Логическое выделение более просто реализовать, так как выбранные символы всегда непрерывны в тексте.

Выборка SelectionSample.java демонстрирует логическое выделение:

Выборка выбора; демонстрация логического выделения

Выполнение текстового Расположения в Приложении Java

В зависимости от которых API Java Вы используете, у Вас могут быть так немного или такое большое управление текстовым расположением, как Вы нуждаетесь:

Обычно, Вы не должны выполнить текстовые операции расположения самостоятельно. Для большинства приложений, JTextComponent лучшее решение для того, чтобы вывести на экран статический и доступный для редактирования текст. Однако, JTextComponent не поддерживает дисплей двойных каре или несмежных выборов в двунаправленном тексте. Если Ваше приложение требует этих функций, или Вы предпочитаете реализовывать свои собственные подпрограммы редактирования текста, можно использовать Java 2-D текстовые API расположения.

Управление текстовым Расположением с Классом TextLayout

TextLayout class поддерживает текст, который содержит многократные стили и символы от различных систем письменности, включая арабский и иврит. (Арабский и иврит особенно трудно вывести на экран, потому что следует изменить и переупорядочить текст, чтобы достигнуть приемлемого представления.)

TextLayout упрощает процесс отображения и измерения текста, даже если Вы работаете с текстом только для английского языка. При использовании TextLayout, можно достигнуть высококачественного книгопечатания без дополнительного усилия.

TextLayout разрабатывается так, чтобы не было никакого существенного воздействия производительности, когда это используется, чтобы вывести на экран простой, однонаправленный текст. Есть некоторые дополнительные издержки обработки когда TextLayout используется, чтобы вывести на экран арабский или еврейский текст. Однако, это обычно находится на порядке микросекунд на символ и во власти выполнения нормального кода для прорисовки.

TextLayout class управляет расположением и упорядочиванием глифов для Вас. Можно использовать TextLayout сделать следующее:

Разметка текста с Классом TextLayout

TextLayout автоматически размечает текст, включая двунаправленный текст, с корректным формированием и упорядочиванием. Правильно сформировать и упорядочить глифов, представляющих строку текста, TextLayout должен знать полный контекст текста:

Основное направление текста обычно устанавливается атрибутом (стиль) на тексте. Если тот атрибут отсутствует, TextLayout следует за Unicode двунаправленный алгоритм и получает основное направление из начальных символов в абзаце.

Отображение Двойных Каре с Классом TextLayout

TextLayout поддерживает информацию о каре, такую как каре Shape, позиция, и угол. Можно использовать эту информацию, чтобы легко вывести на экран каре и в однонаправленном и в двунаправленном тексте. Когда Вы тянете каре для двунаправленного текста, используя TextLayout гарантирует, что каре будут расположены правильно.

TextLayout обеспечивает каре значения по умолчанию Shapes и автоматически поддерживает двойные каре. Для курсива и наклонных глифов, TextLayout производит повернутые каре, как показано в следующем числе. Эти позиции каре также используются в качестве границ между глифами для выделения и поражают тестирование, которое помогает произвести непротиворечивый пользовательский опыт.

Угловые каре

Учитывая смещение вставки, getCaretShapes метод возвращает массив с двумя элементами Shape объекты: элемент 0 содержит каре strong, и элемент 1 содержит слабое каре, если Вы существуете. Чтобы вывести на экран двойные каре, Вы просто тянете оба каре Shape объекты; каре будут автоматически быть представленными в корректных позициях.

Если Вы хотите использовать пользовательские каре, можно получить позицию и угол каре от TextLayout и привлеките их непосредственно.

Выборка HitTestSample.java демонстрирует двойные каре.

Щелчок по o на стороне o к еврейским текстовым записям, что конечный пользователь, по которому щелкают после o, который является частью английского текста. Это располагает слабое (черное) каре рядом с o и каре strong (красное) перед H:

Тестовая Выборка хита, по которой щелкают 'o' на сторону к еврейскому тексту

Щелчок по пространству направо от записей o, что конечный пользователь, по которому щелкают пространство, которое является частью еврейского текста. Это располагает strong (красное) каре рядом с o и слабое каре (черное) перед H:

Тестовая Выборка хита, по которой щелкают пространство направо от 'o'

Перемещение Каре с Классом TextLayout

Можно также использовать TextLayout class, чтобы определить получающееся смещение вставки, когда пользователь нажимает левую или правую клавишу со стрелкой. Данный a TextHitInfo объект, который представляет текущее смещение вставки, getNextRightHit метод возвращает a 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

TextLayout class обеспечивает простой механизм для текста тестирования хита. hitTextChar метод берет x и координаты y от мыши как параметры и возвращает a 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();
    }
  }

Выделение Выборов с Классом TextLayout

Можно получить 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 объект с цветом выделения.


Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Проведение Многократных Линий текста
Следующая страница: Работа с Изображениями