概要

JListのセルレンダラーとして使用しているJEditorPaneに複数リンクを表示し、マウスクリックイベントを転送してHyperlinkEventが発生するように設定します。

サンプルコード

DefaultListModel<SiteItem> m = new DefaultListModel<>();
m.addElement(new SiteItem("aterai",
  Arrays.asList("http://ateraimemo.com", "https://github.com/aterai")));
m.addElement(new SiteItem("example",
  Arrays.asList("http://www.example.com", "https://www.example.com")));

JList<SiteItem> list = new JList<>(m);
list.setFixedCellHeight(120);
list.setCellRenderer(new SiteListItemRenderer());
list.addMouseListener(new MouseAdapter() {
  @Override public void mouseClicked(MouseEvent e) {
    Point pt = e.getPoint();
    int index = list.locationToIndex(pt);
    if (index >= 0) {
      SiteItem item = list.getModel().getElementAt(index);
      Component c = list.getCellRenderer().getListCellRendererComponent(
          list, item, index, false, false);
      if (c instanceof JEditorPane) {
        Rectangle r = list.getCellBounds(index, index);
        c.setBounds(r);
        pt.translate(-r.x, -r.y);
        c.dispatchEvent(new MouseEvent(
            c, e.getID(), e.getWhen(), e.getModifiers() | e.getModifiersEx(),
            pt.x, pt.y, e.getClickCount(), e.isPopupTrigger()));
      }
    }
  }
});
view all

解説

上記のサンプルでは、JListに設定したMouseListenerのクリックイベントをそのListCellRendererとして使用しているJEditorPanedispatchEventで転送し、HyperlinkListenerでリンククリックイベントが取得できるように設定しています。

  • MouseEventは、そのクリック位置をJListからJEditorPane相対に変更する必要がある
    • SwingUtilities.convertMouseEvent(list, e, editor)ではうまく変換できないので、自前で位置を変換し、new MouseEvent(...)でイベントを作り直している

参考リンク

コメント