Summary

JToolTipを親にして背景色などをJToolTip風に設定したJPopupMenuを作成し、その内部に配置したJLabelをドラッグして表示位置を変更します。

Source Code Examples

class ToolTipEditorPane extends JEditorPane {
  private final JPanel panel;

  protected ToolTipEditorPane(JPanel panel) {
    super();
    this.panel = panel;
  }

  @Override public JToolTip createToolTip() {
    JToolTip tip = super.createToolTip();
    tip.addHierarchyListener(e -> {
      boolean showing = e.getComponent().isShowing();
      if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0 && showing) {
        panel.setBackground(tip.getBackground());
        Container p = SwingUtilities.getAncestorOfClass(JPopupMenu.class, panel);
        if (p instanceof JPopupMenu) {
          // ((JPopupMenu) p).setLightWeightPopupEnabled(false);
          ((JPopupMenu) p).show(tip, 0, 0);
        }
      }
    });
    return tip;
  }
}

class DragLabel extends JLabel {
  private transient MouseAdapter handler;

  @Override public void updateUI() {
    removeMouseListener(handler);
    removeMouseMotionListener(handler);
    super.updateUI();
    handler = new PopupDragListener();
    addMouseListener(handler);
    addMouseMotionListener(handler);
    Color bgc = UIManager.getColor("ToolTip.background");
    if (bgc != null) {
      setBackground(bgc.darker());
    }
    setOpaque(true);
  }

  @Override public Dimension getPreferredSize() {
    return new Dimension(16, 64);
  }
}

class PopupDragListener extends MouseAdapter {
  private final Point startPt = new Point();

  @Override public void mousePressed(MouseEvent e) {
    if (SwingUtilities.isLeftMouseButton(e)) {
      Component c = e.getComponent();
      Container popup = SwingUtilities.getAncestorOfClass(JPopupMenu.class, c);
      SwingUtilities.convertMouseEvent(c, e, popup);
      startPt.setLocation(e.getPoint());
    }
  }

  @Override public void mouseDragged(MouseEvent e) {
    if (SwingUtilities.isLeftMouseButton(e)) {
      Component c = e.getComponent();
      Window w = SwingUtilities.getWindowAncestor(c);
      // Popup$HeavyWeightWindow
      if (w != null && w.getType() == Window.Type.POPUP) {
        Point pt = e.getLocationOnScreen();
        w.setLocation(pt.x - startPt.x, pt.y - startPt.y);
      }
    }
  }
}
View in GitHub: Java, Kotlin

Description

Reference

Comment