概要

JTextArea内でマウスカーソルが乗った単語の開始オフセットなどをJToolTipで表示します。

サンプルコード

JTextArea textArea = new JTextArea(txt) {
  @Override public String getToolTipText(MouseEvent e) {
    // Java 9: int pos = viewToModel2D(e.getPoint());
    int pos = viewToModel(e.getPoint());
    String tipText = super.getToolTipText(e);
    try {
      int start = Utilities.getWordStart(this, pos);
      int end = Utilities.getWordEnd(this, start);
      String word = getText(start, end - start);
      // Java 11: if (!word.isBlank()) {
      if (!word.trim().isEmpty()) { // if (!checkTrimEmpty(word)) {
        tipText = String.format("%s(%d-%d)", word, start, end);
      }
    } catch (BadLocationException ex) {
      UIManager.getLookAndFeel().provideErrorFeedback(this);
    }
    return tipText;
  }
};
View in GitHub: Java, Kotlin

解説

  • JTextArea#getToolTipText(MouseEvent)をオーバーライドして以下の手順で単語を取得
    • JTextComponent#viewToModel(Point)でマウスカーソル位置(MouseEvent.getPoint())のドキュメントの先頭からのオフセットを取得
    • Utilities.getWordStart(textArea, offset)で指定したオフセット近くの単語の開始オフセットを取得
    • Utilities.getWordEnd(textArea, offset)で指定したオフセット近くの単語の終了オフセットを取得
    • JTextComponent#getText(offs, len)で単語文字列を取得
    • 取得した文字列が空白のみや空でなければToolTipTextとして使用する

  • Utilities.getWordStart(...)などの内部でBreakIterator.getWordInstance(c.getLocale())を使用しているので日本語環境で実行すれば記号、漢字、ひらがな、カタカナなどの区切りで単語を取得可能
  • Utilities#getWordStart(...)Utilities#getWordEnd(...)Utilities#getNextWord(...)などのドキュメントすべてに「BreakIterator.getWordInstance()を使用すると、実際に語を取得できます。」と記述されているが意味がよく分からない
    • 「Uses BreakIterator.getWordInstance() to actually get the words.」
    • 「実際の単語取得には BreakIterator.getWordInstance() を使用しています。」ぐらいの意味?
  • Utilities.getWordStart(...)などの内部ではBreakIterator.getWordInstance(c.getLocale())を使用して単語を取得してからその開始オフセット、終了オフセットを取得している
    • そのためUtilities.getWordStart(...)Utilities.getWordEnd(...)JTextComponent#getText(...)を実行しなくても一回のBreakIterator.getWordInstance(c.getLocale())で最寄りの単語とその開始オフセット、終了オフセットが取得可能

参考リンク

コメント