---
category: swing
folder: ScrollIndicator
title: JProgressBarでページのスクロールした距離を表示する
title-en: Show page scroll distance with JProgressBar
tags: [JProgressBar, JScrollPane, JScrollBar, BoundedRangeModel, JTextComponent]
author: aterai
pubdate: 2025-11-24T00:34:21+09:00
description: JProgressBarでページのスクロールした距離を表示する進捗インジケーターを作成し、JScrollPaneのヘッダに追加します。
summary-ja: JProgressBarでページのスクロールした距離を表示する進捗インジケーターを作成し、JScrollPaneのヘッダに追加します。
summary-en: We'll create a progress indicator using a JProgressBar to display the distance the page has scrolled and add it to the header of the JScrollPane.
image: https://drive.google.com/uc?id=1J4ecRD48qgfVz3znudq0kz4_YfXU3IVg
---
* Summary [#summary]
JProgressBarでページのスクロールした距離を表示する進捗インジケーターを作成し、JScrollPaneのヘッダに追加します。
`JProgressBar`でページのスクロールした距離を表示する進捗インジケーターを作成し、`JScrollPane`のヘッダに追加します。

#download(https://drive.google.com/uc?id=1J4ecRD48qgfVz3znudq0kz4_YfXU3IVg)

* Source Code Examples [#sourcecode]
#code(link){{
JScrollPane scroll = new JScrollPane(new JTextArea(buf.toString()));
BoundedRangeModel model = scroll.getVerticalScrollBar().getModel();
JProgressBar progress = new ScrollIndicator(model);
scroll.setColumnHeaderView(progress);
// ...

class ScrollIndicator extends JProgressBar {
  protected ScrollIndicator(BoundedRangeModel model) {
    super(model);
  }

  @Override public void updateUI() {
    super.updateUI();
    setUI(new ScrollIndicatorUI());
    setBorder(BorderFactory.createEmptyBorder());
  }

  @Override public double getPercentComplete() {
    long span = model.getMaximum() - model.getMinimum();
    // double currentValue = model.getValue();
    double currentValue = model.getValue() + model.getExtent();
    return  (currentValue - model.getMinimum()) / span;
  }

  @Override public Dimension getPreferredSize() {
    Dimension d = super.getPreferredSize();
    if (getOrientation() == HORIZONTAL) {
      d.height = 4;
    } else {
      d.width = 4;
    }
    return d;
  }
}

class ScrollIndicatorUI extends BasicProgressBarUI {
  @Override public void paintDeterminate(Graphics g, JComponent c) {
    Insets b = progressBar.getInsets();
    Rectangle r = SwingUtilities.calculateInnerArea(progressBar, null);
    // BoundedRangeModel m = progressBar.getModel();
    if (!r.isEmpty()) {
      // int range = m.getMaximum() - m.getMinimum();
      // int extent = (int) Math.floor(r.width *  m.getExtent() / (float) range);
      int amountFull = getAmountFull(b, r.width, r.height); // + extent;
      Graphics2D g2 = (Graphics2D) g.create();
      g2.setColor(UIManager.getColor("ProgressBar.foreground"));
      if (progressBar.getOrientation() == SwingConstants.HORIZONTAL) {
        g2.fillRect(r.x, r.y, amountFull, r.height);
      } else { // VERTICAL
        g2.fillRect(r.x, r.y + r.height - amountFull, r.width, amountFull);
      }
      // Deal with possible text painting
      if (progressBar.isStringPainted()) {
        paintString(g2, r.x, r.y, r.width, r.height, amountFull, b);
      }
      g2.dispose();
    }
  }
}
}}

* Description [#description]
- `JScrollPane#getVerticalScrollBar()`で縦`JScrollBar`を取得し、その`BoundedRangeModel`を共有する`JProgressBar`を作成
-- `JScrollPane#setColumnHeaderView(...)`で`JScrollPane`のカラムヘッダに配置
- 縦`JScrollBar`の表示領域(`JViewport`の高さ)がその`BoundedRangeModel`の`extent`(ノブの高さ)となるが、`JProgressBar`の`BoundedRangeModel`は進捗の描画に`extent`は使用しない(常に`0`)ので、進捗が`100%`になっても`JProgressBar`の右端に`extent`分の塗り残しが発生する
-- このサンプルではこれを解消するため、以下のような調整を行っている
-- 進捗状況の描画領域サイズを計算する`BasicProgressBarUI#getAmountFull(...)`が内部で`JProgressBar#getPercentComplete()`を使用するので、`JProgressBar#getPercentComplete()`をオーバーライドし、縦`JScrollBar`のノブの下辺の位置が`JProgressBar`の現在値となるよう、`BoundedRangeModel#getValue()`ではなく`BoundedRangeModel#getValue() + BoundedRangeModel#getExtent()`の値で進捗のパーセントを求めるよう変更

* Reference [#reference]
- [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/JProgressBar.html#setModel-javax.swing.BoundedRangeModel- JProgressBar#setModel(BoundedRangeModel) (Java Platform SE 8)]
- [[JEditorPaneのミニマップを表示する>Swing/MiniMap]]
- [[JEditorPaneのスクロールに連動してJTreeのノードを選択する>Swing/Scrollspy]]
- [[JTextFieldの表示領域をJScrollBarでスクロールする>Swing/HorizontalVisibility]]

* Comment [#comment]
#comment
#comment