WisdomSoft - for your serial experiences.

9.2 ビューポート

表示領域よりも大きいコンテンツは、コンテンツの一部を表示領域に合わせて描画されます。コンテンツを表示する範囲の管理は JViewport クラスで行われます。

9.2.1 コンテナより大きなコンテンツの管理

コンテナよりも大きなイメージやコンポーネントを扱う場合はビューポートコンテナが提供する機能を利用します。ビューポートは、コンテナに表示するビューと呼ばれるコンポーネントを保有し、ビューポートの左上隅に表示されるビューの座標などを管理する機能を提供しています。

ビューポートとビューの関係は、カメラのファインダーから対象オブジェクトを覗いている関係に似ています。ビューの座標を X 軸に増加するということは、カメラを右手側にスライドさせるということになります。このとき、ファインダーから見える景色は左側に流れます。つまり、ビューポートが表示しているコンポーネントを左側に移動させたように感じるでしょう。座標を Y 軸に増加した場合も、同様にコンポーネントの下側が表示されます。

ビューポートは javax.swing.JViewport クラスで実装されています。このコンテナは、通常ビューを表示するために利用され、他の複数のコンポーネントを表示する通常のコンテナとしては使われることはありません。

javax.swing.JViewport クラス
java.lang.Object
  |
  +--java.awt.Component
        |
        +--java.awt.Container
              |
              +--javax.swing.JComponent
                    |
                    +--javax.swing.JViewport
public class JViewport extends JComponent implements Accessible

JViewport クラスのコンストラクタは引数を受け取らないデフォルトのコンストラクタだけが公開されています。メソッドは、表示するビューを菅るするためのメソッドが定義されているので、これらのメソッドを使ってビューの値を設定してコンポーネントを表示します。

JViewport クラスのコンストラクタとメソッド(抜粋)
コンストラクタ 解説
public JViewport() JViewport を生成する。
メソッド
public void addChangeListener(ChangeListener l) ビューのサイズ、位置、長さが変更されるたびに通知されるリスナを追加する。
public void removeChangeListener(ChangeListener l) 設定されている ChangeListener を削除する。
public ChangeListener[] getChangeListeners() 設定されているすべての ChangeListener の配列を返す。
public void setView(Component view) ビューを設定する。
public Component getView() 設定されているビューを返す。
public void setViewPosition(Point p) ビューポートの左上隅に表示されるビューの座標を設定する。
public Point getViewPosition() ビューポートの左上隅に表示されるビューの座標を返す。
public void setViewSize(Dimension newSize) ビューのサイズを設定する。
public Dimension getViewSize() ビューの現在のサイズを返す。
public Rectangle getViewRect() 起点が getViewPosition、サイズが getExtentSize である矩形を返す。
public void setExtentSize(Dimension newExtent) ビューの座標を使用してビューの可視部分のサイズを設定する。
public Dimension getExtentSize() ビューの可視部分のサイズをビューの座標で返す。

一般的な開発では JViewport クラスのインスタンスを生成することはほとんどないと思われます。このクラスはスクロールの基本となる機能を提供していますが、スクロールを目的に使う場合は後述するスクロールペインを使うことになるでしょう。しかし、スクロールペインは内部に JViewpor コンポーネントを含んでいます。ビューポートはスクロール機能を提供する基本となるクラスなので、例えば独自のスクロール機能を提供する場合などに利用することができるでしょう。

ビューポートを適切に利用するには、まず setView() メソッドを使ってビューポートが管理する唯一の子であるビューを設定します。そして、外部からのスクロール要求などにしたがってビューの位置を setViewPosition() メソッドで操作することで、スクロール処理を簡単に実現することができます。

コード1
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JFrame implements MouseMotionListener , MouseListener {
	public static void main(String args[]) {
		JFrame win = new Test();
		win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		win.setBounds(10 , 10 , 400 , 300);
		win.show();
	}

	Point temp;
	JViewport view = new JViewport();
	public Test() {
		JLabel label = new JLabel(new ImageIcon("test.jpg"));
		view.setView(label);
		view.addMouseListener(this);
		view.addMouseMotionListener(this);

		getContentPane().add(view);
	}

	public void mouseClicked(MouseEvent e) {}
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}
	public void mousePressed(MouseEvent e) { temp = e.getPoint(); }
	public void mouseReleased(MouseEvent e) {}

	public void mouseDragged(MouseEvent e) {
		Point offset = new Point(
			e.getPoint().x - temp.x , e.getPoint().y - temp.y
		) ;
		Point ptViewPos = new Point(
			view.getViewPosition().x + offset.x ,
			view.getViewPosition().y + offset.y
		);

		view.setViewPosition(ptViewPos);
		setTitle("X=" + ptViewPos.x + ",Y=" + ptViewPos.y);
		temp = e.getPoint();
	}
	public void mouseMoved(MouseEvent e) {}
}
実行結果
コード1 実行結果

コード1は、ビューポートのスクロール機能を利用してマウスのドラッグでコンテンツの位置を移動させるというプログラムです。このプログラムが表示しているのは、JLabel コンポーネントをビューに設定している JViewport です。JLabel コンポーネントは test.jpg という名前のイメージファイルをアイコンとして表示しています。

まず、Test クラスはコンストラクタで、ビューポートにマウスリスナを追加してマウスの移動や入力を監視します。マウスのボタンが押されるとその位置が記録され、ボタンを押したままドラッグすることで以前の位置と現在のカーソルの位置を比較したオフセットを、ビューポートの位置に加算しています。その結果、マウスカーソルをドラッグすると、その方向にイメージをスクロールすることができます。

ビューポートとビューの位置の関係は、単純な位置関係とは異なることに注意してください。Y 座標を増加させるとビューは上に移動し、逆に減らした場合はビューが下に移動します。X 座標を増加させるとビューは左に移動し、減少させると右に移動します。この関係は、ウィンドウのタイトルバーに表示する座標値を見れば確認できるでしょう。プログラムを実行してドラッグをすると、イメージはマウスとは逆の方向に移動します。水平スクロールバーを右に移動させると、コンテンツは左に移動し、垂直スクロールバーを下に移動させると、コンテンツが上に移動するのはこのためです。