不確定進捗バー

このドキュメントでは、不確定進捗バーを実装するために行われた変更について説明します。このバーは、通常の進捗バーと似た外観のGUIコンポーネントであり、通常の進捗バーと同様に、時間のかかる操作が発生していることを示すアニメーションを使用します。ただし通常の進捗バーと異なり、不確定進捗バーは、操作完了までの程度は示しません。このドキュメントには次のセクションがあります。

新規JProgressBar API

デフォルトで、いくつかのJProgressBarコンストラクタの中の1つを使用して作成される各進捗バーは、確定的です。setIndeterminateメソッドを使用すると、どのようなJProgressBar不確定進捗バーでも作成できます。

    pb.setIndeterminate(true);

不確定進捗バーの表示は、常に動いています。進捗バーを確定的にして現在値を最小値に設定することで、アニメーションを停止し、進捗バーをクリアすることができます。たとえば、

    pb.setValue(pb.getMinimum());
    pb.setIndeterminate(false);

任意の時点で、確定モードと不確定モードを切り替えることができます。進捗バーが不確定かどうかは、isIndeterminateメソッドを使用して確認できます。

進捗バーが不確定な場合は、そのモデル(BoundedRangeModel)が無視されます。ただし、不確定進捗バー用に更新されなかったL&Fがこのモデルを使用する可能性があるため、モデルが存在し、適切なデータを含んでいる必要があります。

新規UIデフォルト

進捗バーのアニメーションの速度を開発者が制御できるように、2つの新規UIデフォルトが追加されました。

ProgressBar.cycleTime」UIデフォルトを使用して、ルック・アンド・フィールの実装者やほかの開発者が、アニメーションの各サイクルにかかる時間を、ミリ秒単位で指定します。たとえば、サイクル時間が500の場合は、不確定モードの進捗バーのアニメーションは、秒あたり2回繰り返されます。デフォルトの描画コードは、この値を再ペイントの間隔、ボックスの長さ、およびコンポーネントの内部領域とともに使用し、ボックスが描画されるごとに跳躍する長さを決定します。この値は、再ペイント間隔の偶数倍にする必要があります。たとえば、再ペイントの間隔が100の場合は、有効なサイクル時間は200、1000、1200などであり、100または500ではありません。ユーザーが無効なサイクル時間を指定した場合は、不確定進捗バーのコードによって適切な値になるようにサイクル時間が自動的に増やされます。

再ペイントの間隔とサイクル時間のデフォルトは、次のように設定します。

    UIManager.put("ProgressBar.repaintInterval", new Integer(250));
    UIManager.put("ProgressBar.cycleTime", new Integer(6000));

再ペイントの間隔とサイクル時間を入手するには、次のようにします。

    int interval = UIManager.getInt("ProgressBar.repaintInterval");
    int totalTime = UIManager.getInt("ProgressBar.cycleTime");

基本的な実装、JLF、Motif、およびWindows実装では、進捗バーが不確定モードに切り替えられた場合にのみ、これらのデフォルトが確認されます。

新規BasicProgressBarUI API

プログラマが進捗バーのルック・アンド・フィールを実装するときの役に立つように、次のAPIが BasicProgressBarUIクラスに追加されました。

ペイント関連のメソッド

アニメーションの現行フレームのインデックスを設定および取得するメソッド

カスタムのアニメーション・スレッドを開始または停止するメソッド

従来は進捗バーのペイントをすべて事前に形成したpaintメソッドは、現在では、進捗バーの不確定性関連のプロパティ値に応じて、すべての描画をpaintDeterminateまたはpaintIndeterminateに委譲します。進捗バーが不確定モードの場合は、paintメソッド(したがってpaintIndeterminateメソッドも)は、再ペイントの間隔(ミリ秒)ごとに実行されます。paintIndeterminateメソッドは進捗バーをアニメーションの状態に合わせてペイントする必要がありますが、この状態はgetAnimationIndexメソッドで指定されます。

getBoxメソッドを使用して、実装で跳躍ボックスのペイントをカスタマイズできます。たとえば、MetalProgressBarUIがそのpaintIndeterminateメソッド内でgetBoxを呼び出してスーパー・クラスのBasicProgressBarUIにボックスを描画させ、その後輪郭線をボックスに追加します。getBoxメソッドをオーバーライドすることで、paintIndeterminateをふたたび実装しなくても、跳躍ボックスのサイズと位置を完全に制御することができます。

paintIndeterminateまたはgetBoxをオーバーライドする場合は、有効な値で正しく循環するように、incrementAnimationIndexもオーバーライドする必要がある可能性があります。最初の描画を示す値は0です。規定により、2番目の描画が1、3番目の描画が2というように続きます。最後の有効な値は、規定により、アニメーション・サイクル内の総描画数から1を引いたものです。描画総数を判断するには、再ペイントの間隔と、おそらく、コンポーネントのサイズも考慮に入れる必要があります。「規定により」が暗黙に示すように、アニメーションのインデックスは、0がアニメーション・サイクルの始まりを示しているかぎり、希望する意味と値を持つように実装することができます。

提供されたアニメーション・スレッドを使用しない場合は、2つのxxxAnimationTimerメソッドをオーバーライドする必要があります。これで、定期的にアニメーションのインデックスを増加させ、進捗バー上でrepaintを呼び出す独自の実装を提供できます。

進捗バーに関する開発作業の間接的な結果として、次の新しいメソッドがSwingUtilitiesに追加されました。

calculateInnerAreaメソッドは、描画するすべてのクラスにとって有用です。このメソッドによって、コンポーネントが描画できる領域、つまりボーダー領域(コンポーネントのイン・セット)を除くコンポーネントのすべての部分を含む四角形(コンポーネントの座標系内)が返されます。

既存の進捗バー実装の変換

既存のL&Fの不確定進捗バーを変換することは、比較的単純です。既存のL&Fの進捗バーUIがpaintをオーバーライドしない、またはオーバーライドしてもsuper.paintを呼び出す場合は、不確定進捗バーが自動的にサポートされます。WindowsProgressBarUIMotifProgressBarUI、およびMetalProgressBarUIがこれに相当します。

L&Fの進捗バーUIクラスがBasicProgressBarUIのサブクラスであって、スーパー・クラスを呼び出さなくてもpaintをオーバーライドする場合は、確定モードが引き続き作用しますが、不確定モードも確定モードと同じように見えます。

既存の描画コードをpaintメソッドから取出し、新しいpaintDeterminateメソッドに移す必要があります。不確定なペイントのためのコードは、新しいpaintIndeterminateメソッドに移す必要があります。結局、上記の作業がすべて可能であれば、super.paintが呼び出されないかぎり、paintメソッドをオーバーライドすべきではありません。その理由は、paintメソッドのBasicProgressBarUI実装がデフォルトのアニメーション・スレッドを処理して、パフォーマンスと動作を拡張できるからです。

Macのルック・アンド・フィール (これ以上保守が行われないOracleバージョンと、Appleバージョンの両方)は、スーパークラス・バージョンを呼び出さないでpaintをオーバーライドするルック・アンド・フィールの例です。

不確定なペイントに対するスレッドのスキームがすでにある場合は、startAnimationTimerおよびstopAnimationTimerをオーバーライドして、そのスキームを使い続けることができます。または、単に独自のスレッド・コードを削除して、提供されたスキームを使うこともできます。

実装の詳細

BasicProgressBarUIクラスには、不確定進捗バーの実装のほとんどが含まれています。描画コードを除けば、実装コードのほとんどは、アニメーション・スレッドを実装するAnimatorと、不確定モードの切替えを待機するPropertyChangeHandlerの、2つのprivate内部クラス内にあります。

Animatorは、SwingのTimerクラスを使用してデフォルトのアニメーション・スレッドを実装します。Animatorインスタンスは、必要な場合にBasicProgressBarUI.startAnimationTimerメソッドによって作成されます。このメソッドは、進捗バーが不確定モードに切り替わったときにプロパティ・ハンドラによって呼び出されます。進捗バーが不確定になると、Animatorのタイマーが、再ペイントの間隔(ミリ秒)ごとに1回、アクション・イベントを起動します。Animatorのアクション・イベント・ハンドラが、incrementAnimationIndexを呼び出し、続いてrepaintを呼び出します(repaintによりpaintIndeterminateが実行されます)。再ペイントの間隔は、ProgressBar.repaintIntervalのUIデフォルトで指定されます。これはstartAnimationTimerでチェックされます。

PropertyChangeHandlerは、自身を進捗バー上のプロパティのリスナーとして登録します。「不確定」なプロパティが検出されると、ハンドラは変更を通知してstopAnimationTimerまたはstartAnimationTimerのどちらかを呼び出します。

新規APIのためのJavadoc

javax.swing.JProgressBar内:

    public void setIndeterminate(boolean newValue)

    public boolean isIndeterminate()


javax.swing.plaf.basic.BasicProgressBarUI内:

    protected void paintIndeterminate(Graphics g, JComponent c)

    protected void paintDeterminate(Graphics g, JComponent c)

    protected int getAnimationIndex()

    protected void setAnimationIndex(int newValue)

    protected void incrementAnimationIndex()

    protected void startAnimationTimer()

    protected void stopAnimationTimer()

    protected Rectangle getBox(Rectangle r)


javax.swing.SwingUtilities内:

    public static Rectangle calculateInnerArea(JComponent c, Rectangle r)

Copyright © 1993, 2020, Oracle and/or its affiliates. All rights reserved.