• category: swing folder: SmyliyIconStyle title: JTextPaneに入力した文字をアイコンに変換する tags: [JTextPane, Icon, StyledDocument, StyleContext] author: aterai pubdate: 2015-09-14T03:54:53+09:00 description: JTextPaneに入力した文字を顔文字アイコンに変換して表示します。 image: https://lh3.googleusercontent.com/-NLmesRy01ro/VfXFpQeOQSI/AAAAAAAAOBo/L7P-9nfFeNk/s800-Ic42/SmyliyIconStyle.png

概要

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に限定することで高速化
    • スタイルにアイコン属性だけでなく、文字色属性などを追加する場合、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);
      

参考リンク

コメント