概要

JTextAreaMouseListenerを追加し、マウス左ボタンの長押しで単語選択、右クリックでのフォーカス移動などの機能を追加します。

サンプルコード

class TextComponentMouseHandler extends MouseAdapter {
  private final AtomicInteger count = new AtomicInteger(0);
  private final Timer holdTimer = new Timer(1000, null);
  private final List<String> list = Arrays.asList(
      DefaultEditorKit.selectWordAction,
      DefaultEditorKit.selectLineAction,
      DefaultEditorKit.selectParagraphAction,
      DefaultEditorKit.selectAllAction);

  protected TextComponentMouseHandler(JTextComponent textArea) {
    super();
    holdTimer.setInitialDelay(500);
    holdTimer.addActionListener(e -> {
      Timer timer = (Timer) e.getSource();
      if (timer.isRunning()) {
        int i = count.getAndIncrement();
        if (i < list.size()) {
          String cmd = list.get(i);
          textArea.getActionMap().get(cmd).actionPerformed(e);
        } else {
          timer.stop();
          count.set(0);
        }
      }
    });
  }

  @Override public void mousePressed(MouseEvent e) {
    boolean isSingleClick = e.getClickCount() == 1;
    if (isSingleClick) {
      JTextComponent textArea = (JTextComponent) e.getComponent();
      if (!textArea.hasFocus()) {
        textArea.requestFocusInWindow();
      }
      if (textArea.getSelectedText() == null) {
        // Java 9: int pos = textArea.viewToModel2D(e.getPoint());
        int pos = textArea.viewToModel(e.getPoint());
        textArea.setCaretPosition(pos);
      }
      if (e.getButton() == MouseEvent.BUTTON1) {
        holdTimer.start();
      }
    }
  }

  @Override public void mouseReleased(MouseEvent e) {
    holdTimer.stop();
    count.set(0);
  }

  @Override public void mouseDragged(MouseEvent e) {
    mouseReleased(e);
  }
}
View in GitHub: Java, Kotlin

解説

  • マウス左ボタンの長押し
    • 1.5秒後にgetActionMap().get(DefaultEditorKit.selectWordAction)アクションを実行して単語選択
    • 左ボタンの長押しが継続している場合は2.5秒後にgetActionMap().get(DefaultEditorKit.selectLineAction)アクションを実行して行選択
    • 3.5秒後にgetActionMap().get(DefaultEditorKit.selectParagraphAction)アクションを実行してパラグラフ選択
    • 4.5秒後にgetActionMap().get(DefaultEditorKit.selectAllAction)アクションを実行して全選択
    • 以降はタイマーをストップ
  • MouseListener#mousePressed(...)をオーバーライド
    • シングルクリック、かつJTextAreaにフォーカスが存在しない場合は右、中ボタンでもJTextArea#requestFocusInWindow()を実行してフォーカスを取得
      • また文字列選択されていない場合は右、中ボタンでもキャレットをクリック位置に移動
    • 左ボタンのシングルクリックの場合は長押しのタイマーを起動
    • デフォルトのダブルクリックには単語選択が割り当てられているのでこれに干渉しないよう注意が必要
  • MouseListener#mouseReleased(...)MouseMotionListener#mouseDragged(...)をオーバーライド
    • 長押しのタイマーを停止、リセット

参考リンク

コメント