概要

JInternalFrameのリサイズ中に表示されるアウトラインを色反転の直線から点線に変更してJLayer上に描画します。

スクリーンショット

Swing/OutlineDragStroke.png

サンプルコード

Rectangle rubberBand = new Rectangle();
JDesktopPane desktop = new JDesktopPane();
desktop.setDesktopManager(new DefaultDesktopManager() {
  @Override public void beginResizingFrame(JComponent f, int direction) {
    desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
    super.beginResizingFrame(f, direction);
  }

  @Override public void resizeFrame(JComponent f, int newX, int newY, int newWidth, int newHeight) {
    if (desktop.getDragMode() == JDesktopPane.OUTLINE_DRAG_MODE) {
      super.resizeFrame(f, newX, newY, 0, 0);
      rubberBand.setBounds(newX, newY, newWidth, newHeight);
      desktop.repaint();
    } else {
      super.resizeFrame(f, newX, newY, newWidth, newHeight);
    }
  }

  @Override public void endResizingFrame(JComponent f) {
    desktop.setDragMode(JDesktopPane.LIVE_DRAG_MODE);
    if (!rubberBand.isEmpty()) {
      super.resizeFrame(f, rubberBand.x, rubberBand.y, rubberBand.width, rubberBand.height);
      rubberBand.setBounds(0, 0, 0, 0);
    }
    super.endResizingFrame(f);
  }
});
add(new JLayer<>(desktop, new LayerUI<JDesktopPane>() {
  @Override public void paint(Graphics g, JComponent c) {
    super.paint(g, c);
    if (c instanceof JLayer) {
      JDesktopPane desktop = (JDesktopPane) ((JLayer<?>) c).getView();
      if (desktop.getDragMode() == JDesktopPane.OUTLINE_DRAG_MODE) {
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setPaint(Color.GRAY);
        g2.setStroke(makeDotStroke());
        g2.draw(rubberBand);
        g2.dispose();
      }
    }
  }
}));
View in GitHub: Java, Kotlin

解説

  • DefaultDesktopManager#beginResizingFrame(...)をオーバーライドしてJInternalFrameのリサイズが開始されたらドラッグスタイルをJDesktopPane.OUTLINE_DRAG_MODEに変更
  • DefaultDesktopManager#resizeFrame(...)をオーバーライドしてデフォルトのリサイズアウトラインを幅高さ0に変更して非表示化
    • 別途JLayerでアウトラインを描画するため、アウトラインの位置とサイズをRectangleに記憶してJDesktopPane#repaint()を実行
    • LayerUI#paint(...)をオーバーライドして点線で上記のRectangleを描画
    • DefaultDesktopManager#resizeFrame(...)内でアウトラインは描画されているのでJLayerを使用せずにここで描画も実行したいが、Graphics g = JComponent.safelyGetGraphics(desktopPane)などのメソッドがパッケージプライベートなので使用できない
  • DefaultDesktopManager#beginResizingFrame(...)をオーバーライドしてドラッグスタイルをJDesktopPane.LIVE_DRAG_MODEに戻す
    • 記憶したRectangleJInternalFrameをリサイズするため最後に一回super.resizeFrame(f, rubberBand.x, rubberBand.y, rubberBand.width, rubberBand.height)を実行する必要がある

参考リンク

コメント