ページの先頭行へ戻る
Interstage Studio J Business Kit GUIライブラリ ユーザーズガイド
FUJITSU Software

4.1.7 画面のスクロール表示

画面制御機能が提供する画面のクラスで、JFCScrollablePanelあるいはJFLScrollablePanelから派生した以下のクラスが、スクロール機能を持ちます。

これらのスクロールパネルは、内部で可視領域(ビューポート)と仮想領域(ビューパネル)を持ちます。

可視領域のサイズはスクロールパネルのサイズに合わせて自動的に調整します。仮想領域が可視領域のサイズより大きいとき、スクロール機能を利用して仮想領域の表示位置を動かすことができます。スクロール機能には、メソッド呼出しによるスクロールと、スクロールバー操作によるスクロールがあります。

スクロールパネルは、この上にContainerの派生クラスである可視領域を貼り付けて、更に可視領域にContainerの派生クラスである仮想領域を貼り付けた3階層パネルの構造になっています。このため、スクロールパネルの画面をカスタマイズしたい場合(例:マウスカーソルを砂時計表示したい場合など)は、getViewPanelメソッドを利用して仮想領域を取得してから、仮想領域に対して操作を行う必要があります。ただし、以下メソッドは仮想領域に対して作用するように設計されているため、ユーザは普通のパネルと同様に利用することができます。

スクロールパネルの開発手順

  1. 仮想領域のサイズを設定します。

    スクロールパネルのコンストラクタへの引数として指定するか、setViewSizeメソッドを利用して、動的に仮想領域のサイズを設定します。

    仮想領域は可視領域より小さくても問題ありませんが、少なくとも貼り付けた部品(コンポーネント)がすべて収まる領域を確保する必要があります。必要十分なサイズを確保しなかった場合、仮想領域範囲外に貼られた部品は正しく描画されません。

    仮想領域のサイズは必ず設定する必要があります。ただし、JFCScrollablePanelのスクロールバー表示方針がPREVENT_SCROLL の場合、仮想領域は自動的に可視領域に収まるようにリサイズされます。

  2. スクロールバー表示方針を設定します。

    スクロールパネルのコンストラクタへの引数として指定するか、setScrollbarDisplayPolicyメソッドを利用して、動的にスクロールバー表示方針を設定します。また、スクロールバー表示方針を取得するには、getScrollbarDisplayPolicyメソッドを利用します。

    スクロールパネルには、以下の4種類のスクロールバー表示方針があります。

    表4.8 4種類のスクロールバー表示方針

    PREVENT_SCROLL

    すべてのスクロール機能を利用しません。この方針がデフォルトとなります。

    SCROLLBARS_ALWAYS

    すべてのスクロール機能を利用し、常にスクロールバーを表示します。

    SCROLLBARS_AS_NEEDED

    スクロール機能を利用し、スクロールバーは仮想領域が可視領域より大きい場合に自動的に表示します。

    SCROLLBARS_NEVER

    メソッド呼出しによるスクロール機能を利用しますが、常にスクロールバーを表示しません。

  3. メソッド呼出しによるスクロール機能

    スクロールバーを操作することにより、仮想領域の表示部分を移動(スクロール)することができますが、メソッド呼出しによるスクロールも可能です。ただし、スクロールバー表示方針がPREVENT_SCROLLの場合は、メソッド呼出しによるスクロールはできません。また、仮想領域が可視領域より大きい状態である必要があります。

    スクロールには以下のメソッドが利用できます。

    • moveViewPort(int, int)

    • scrollViewPort(Component, int)

    • showUpComponent(Component, int)

    • setScrollPosition(int,int)

    • setScrollPosition(Point)

JFLScrollablePanelJFCScrollablePanelスクロール用メソッドの違い

以下に各メソッドの特長を説明します。

メソッド名

特長

備考

setScrollPosition

スクロールパネルのビューパネルの左上からの座標(絶対位置)を指定してスクロールさせます。

決められた位置にスクロールさせる場合に使用します。

moveViewPort

現在のスクロール位置(getScrollPositionの復帰値と同値)からの差分(相対位置)を指定してスクロールさせます。

決められた量だけをスクロールさせる場合に使用します。

scrollViewPort

ビューポート上に表示させたいコンポーネントを指定してスクロールさせます。
本メソッドの第2引数に、TOPまたはBOTTOMを指定した場合はY軸だけスクロールし、RIGHTまたはLEFTを指定した場合はX軸だけスクロールします。
X軸かY軸のどちらかにだけ作用します。

特定のコンポーネントを表示させるときに便利です。
(例)コンポーネントがスクロールパネルの下部に表示されるように、Y軸だけスクロールさせる場合
scrollViewPort(<表示させるコンポーネント>, BOTTOM)

showUpComponent

スクロールパネル上に表示させたいコンポーネントを指定してスクロールさせます。
本メソッドの第2引数に、ビューポート上の位置を指定します。
X軸かY軸の両方に作用します。

特定のコンポーネントを表示させるときに便利です。
(例)コンポーネントがビューポートの下端中央部に表示されるように、X軸とY軸の両方をスクロールさせる場合
showUpComponent(<表示させるコンポーネント>, BOTTOM_CENTER)

注意

JFCScrollablePanelに追加したJFTextAreaのキャレットが正しく描画されません

1画面にスクロールバーがいくつも入れ子になっているというユーザインタフェースの場合、JFTextAreaのキャレットがスクロールのクリップ範囲外にある時、描画時にキャレットが描画されない状況になります。
1画面にスクロールバーがいくつも入れ子になっているようなユーザインタフェース設計を見直すことが本質的な対応策となりますが、困難な場合は、JFCScrollablePanelのビューポートのスクロールバーが操作されたときに再描画を行うことで回避することができます。次の手順で、コーディングしてください。

  1. JFCScrollablePanel.getVAdjustable().addAdjustmentListener()で、AdjustmentListenerを追加します。

  2. AdjustmentListenerのadjustmentValueChanged()内で、JFCScrollablePanel.getViewPanel().repaint()を実行します。

ポイント

JFLScrollablePanel/JFCScrollablePanel上のコンポーネントが見えるようにスクロールする方法

スクロールパネルのshowUpComponentまたはscrollViewPortメソッドを使用します。これらのメソッドの引数にコンポーネントと表示位置を指定するだけでスクロールができるため、複雑な座標計算が不要になります。

フォーカス遷移先のコンポーネントが表示されるようにスクロールする例を以下に示します。

 1: import java.awt.BorderLayout;
 2: import java.awt.Component;
 3: import java.awt.Dimension;
 4: import java.awt.Rectangle;
 5: import java.awt.SystemColor;
 6: import java.awt.event.FocusEvent;
 7: import java.awt.event.FocusListener;
 8: import java.awt.event.WindowAdapter;
 9: import java.awt.event.WindowEvent;
10: import java.util.HashMap;
11: import java.util.Map;
12: import com.fujitsu.jbk.gui.JFFieldString;
13: import com.fujitsu.jbk.gui.JFFrame;
14: import com.fujitsu.jbk.gui.JFMultiLineLabel;
15: import com.fujitsu.jbk.gui.ctrl.JFLScrollablePanel;
16:
17: public class ScrollPanel extends JFLScrollablePanel implements FocusListener {
18:     private static final long serialVersionUID = 5406501414644165329L;
19:     private Map<Component, JFMultiLineLabel> relatedLabel = new HashMap<Component, JFMultiLineLabel>();
20:
21:     ScrollPanel() {
22:         super(SCROLLBARS_AS_NEEDED, null, new Dimension(330, 250));
23:         setBackground(SystemColor.control);
24:         createComponents("郵便番号", new Rectangle(10,  10, 100, 20), new Rectangle(120,  10, 100, 20));
25:         createComponents("住所1",    new Rectangle(10,  50, 100, 20), new Rectangle(120,  50, 200, 20));
26:         createComponents("住所2",    new Rectangle(10,  90, 100, 20), new Rectangle(120,  90, 200, 20));
27:         createComponents("名前",     new Rectangle(10, 130, 100, 20), new Rectangle(120, 130, 100, 20));
28:         createComponents("TEL",      new Rectangle(10, 170, 100, 20), new Rectangle(120, 170, 100, 20));
29:         createComponents("FAX",      new Rectangle(10, 210, 100, 20), new Rectangle(120, 210, 100, 20));
30:     }
31:
32:     private void createComponents(String label, Rectangle r1, Rectangle r2){
33:         JFMultiLineLabel l = new JFMultiLineLabel(label);
34:         JFFieldString f = new JFFieldString();
35:         l.setBounds(r1);
36:         f.setBounds(r2);
37:         f.addFocusListener(this); //JFFieldStringに対してフォーカスリスナを設定する
38:         add(l);
39:         add(f);
40:         relatedLabel.put(f, l); //JFFieldStringにJFMultiLineLabelを関連付ける
41:     }
42:
43:     public void focusGained(FocusEvent e) {
44:         Component c = (Component)e.getSource();
45:         if(c instanceof JFFieldString && isAncestorOf(c)==true){
46:             //フォーカス遷移先のJFFieldStringに関連付けられたJFMultiLineLabelが左下に表示されるようにスクロールする
47:             showUpComponent(relatedLabel.get(c), BOTTOM_LEFT);
48:         }
49:     }
50:
51:     public void focusLost(FocusEvent e) {}
52:
53:     public static void main(String[] args) {
54:         JFFrame frame = new JFFrame("Scroll Sample");
55:         frame.setSize(300, 200);
56:         frame.add(new ScrollPanel(), BorderLayout.CENTER);
57:         frame.addWindowListener(new WindowAdapter() {
58:             public void windowClosing(WindowEvent e) {System.exit(0);}
59:         });
60:         frame.setVisible(true);
61:     }
62: }