画面制御機能が提供する画面のクラスで、JFCScrollablePanelあるいはJFLScrollablePanelから派生した以下のクラスが、スクロール機能を持ちます。
JFCEntryPanel
JFLEntryScrollablePanel
JFCEntryInterfacePanel
JFLEntryInterfaceScrollablePanel
JFCMultiPagePanel
JFLMultiPageScrollablePanel
これらのスクロールパネルは、内部で可視領域(ビューポート)と仮想領域(ビューパネル)を持ちます。
可視領域のサイズはスクロールパネルのサイズに合わせて自動的に調整します。仮想領域が可視領域のサイズより大きいとき、スクロール機能を利用して仮想領域の表示位置を動かすことができます。スクロール機能には、メソッド呼出しによるスクロールと、スクロールバー操作によるスクロールがあります。
スクロールパネルは、この上にContainerの派生クラスである可視領域を貼り付けて、更に可視領域にContainerの派生クラスである仮想領域を貼り付けた3階層パネルの構造になっています。このため、スクロールパネルの画面をカスタマイズしたい場合(例:マウスカーソルを砂時計表示したい場合など)は、getViewPanelメソッドを利用して仮想領域を取得してから、仮想領域に対して操作を行う必要があります。ただし、以下メソッドは仮想領域に対して作用するように設計されているため、ユーザは普通のパネルと同様に利用することができます。
部品の追加/削除(add、remove、removeAll)
レイアウトの取得/設定(getLayout、setLayout)
前景色の取得/設定(getForeground、setForeground)
背景色の取得/設定(getBackground、setBackground)
最初にフォーカスが移動する部品の取得/設定(getFirstFocusComponent、setFirstFocusComponent)
フォーカス移動のラップアラウンド状態の取得/設定(isWrapAround、setWrapAround)
キーボードのタブキーによるフォーカス移動ができるかどうかの取得(isFocusTraversable)
スクロールパネルの開発手順
仮想領域のサイズを設定します。
スクロールパネルのコンストラクタへの引数として指定するか、setViewSizeメソッドを利用して、動的に仮想領域のサイズを設定します。
仮想領域は可視領域より小さくても問題ありませんが、少なくとも貼り付けた部品(コンポーネント)がすべて収まる領域を確保する必要があります。必要十分なサイズを確保しなかった場合、仮想領域範囲外に貼られた部品は正しく描画されません。
仮想領域のサイズは必ず設定する必要があります。ただし、JFCScrollablePanelのスクロールバー表示方針がPREVENT_SCROLL の場合、仮想領域は自動的に可視領域に収まるようにリサイズされます。
スクロールバー表示方針を設定します。
スクロールパネルのコンストラクタへの引数として指定するか、setScrollbarDisplayPolicyメソッドを利用して、動的にスクロールバー表示方針を設定します。また、スクロールバー表示方針を取得するには、getScrollbarDisplayPolicyメソッドを利用します。
スクロールパネルには、以下の4種類のスクロールバー表示方針があります。
PREVENT_SCROLL | すべてのスクロール機能を利用しません。この方針がデフォルトとなります。 |
SCROLLBARS_ALWAYS | すべてのスクロール機能を利用し、常にスクロールバーを表示します。 |
SCROLLBARS_AS_NEEDED | スクロール機能を利用し、スクロールバーは仮想領域が可視領域より大きい場合に自動的に表示します。 |
SCROLLBARS_NEVER | メソッド呼出しによるスクロール機能を利用しますが、常にスクロールバーを表示しません。 |
メソッド呼出しによるスクロール機能
スクロールバーを操作することにより、仮想領域の表示部分を移動(スクロール)することができますが、メソッド呼出しによるスクロールも可能です。ただし、スクロールバー表示方針がPREVENT_SCROLLの場合は、メソッド呼出しによるスクロールはできません。また、仮想領域が可視領域より大きい状態である必要があります。
スクロールには以下のメソッドが利用できます。
moveViewPort(int, int)
scrollViewPort(Component, int)
showUpComponent(Component, int)
setScrollPosition(int,int)
setScrollPosition(Point)
JFLScrollablePanelとJFCScrollablePanelのスクロール用メソッドの違い
以下に各メソッドの特長を説明します。
メソッド名 | 特長 | 備考 |
---|---|---|
setScrollPosition | スクロールパネルのビューパネルの左上からの座標(絶対位置)を指定してスクロールさせます。 | 決められた位置にスクロールさせる場合に使用します。 |
moveViewPort | 現在のスクロール位置(getScrollPositionの復帰値と同値)からの差分(相対位置)を指定してスクロールさせます。 | 決められた量だけをスクロールさせる場合に使用します。 |
scrollViewPort | ビューポート上に表示させたいコンポーネントを指定してスクロールさせます。 | 特定のコンポーネントを表示させるときに便利です。 |
showUpComponent | スクロールパネル上に表示させたいコンポーネントを指定してスクロールさせます。 | 特定のコンポーネントを表示させるときに便利です。 |
注意
JFCScrollablePanelに追加したJFTextAreaのキャレットが正しく描画されません
1画面にスクロールバーがいくつも入れ子になっているというユーザインタフェースの場合、JFTextAreaのキャレットがスクロールのクリップ範囲外にある時、描画時にキャレットが描画されない状況になります。
1画面にスクロールバーがいくつも入れ子になっているようなユーザインタフェース設計を見直すことが本質的な対応策となりますが、困難な場合は、JFCScrollablePanelのビューポートのスクロールバーが操作されたときに再描画を行うことで回避することができます。次の手順で、コーディングしてください。
JFCScrollablePanel.getVAdjustable().addAdjustmentListener()で、AdjustmentListenerを追加します。
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: } |