概要

JTextPaneに入力した文字を顔文字アイコンに変換して表示します。

サンプルコード

private void update(DefaultStyledDocument doc, int offset) {
  final Element elm = doc.getCharacterElement(offset);
  EventQueue.invokeLater(new Runnable() {
    @Override public void run() {
      try {
        int start = elm.getStartOffset();
        int end = elm.getEndOffset();
        System.out.format("start: %d, end: %d%n", start, end);
        String text = doc.getText(start, end - start);
        int pos = text.indexOf(FACE);
        while (pos > -1) {
          Style face = doc.getStyle(FACE);
          doc.setCharacterAttributes(start + pos, FACE.length(), face, false);
          pos = text.indexOf(FACE, pos + FACE.length());
        }
      } catch (BadLocationException ex) {
        ex.printStackTrace();
      }
    }
  });
}
View in GitHub: Java, Kotlin

解説

  • StyleConstants.setIcon(doc.addStyle(":)", null), new FaceIcon())でドキュメントにアイコン属性を設定
  • 文字列の追加、削除が実行されると文字列から:)を検索
  • 発見した文字列に対してStyledDocument#setCharacterAttributes(...)でそのアイコン属性を適用
  • :)から一文字削除してもアイコンが解除されない制限がある
  • メモ:
    • 顔文字の検索範囲をStyledDocument#getCharacterElement(offset)で取得したElementに限定することで高速化
      • LabelViewを継承するViewにしたほうが速いかもしれない
    • スタイルにアイコン属性だけでなく、文字色属性などを追加する場合、MutableAttributeSet inputAttributes = textPane.getInputAttributes();inputAttributes.removeAttributes(inputAttributes)などを実行して、後続の入力文字列に属性が引き継がれないようにする必要がある?
      Style def = StyleContext.getDefaultStyleContext()
                              .getStyle(StyleContext.DEFAULT_STYLE);
      Style face = doc.addStyle(FACE, def);
      StyleConstants.setIcon(face, new FaceIcon());
      StyleConstants.setForeground(face, Color.RED);
      

参考リンク

コメント