スクロールバー

(サンプル一覧を表示する)

FlashDevelop を使って、スクロールバーのテストをしてみました。

このサンプルでは、1 ずつ値を動かすボタンを付けていないので、
おおざっぱに値を取りたい時にはこれでも良いと思いますが、
細かく値を取りたい時には不便かもしれません。

あと、コード側から値をセットすることでスクロールバーの
つまみの位置が 自動で調整される処理を入れてないので、
それがものすごく不便かもしれません。
つまりどういうことかというと、ユーザがこのスクロールバーを
使って値をセットすることはできますが、
システム側から、スクロールバーを簡単に動かす仕組みが
用意されていないということです。
プロパティにセットされた値からつまみの位置を求めて、
つまみの X 座標をそこに移動させる処理を追加することで
これは解決できます。
Flash の実行画面
スクロールバー

Flashプレーヤーが入っていないか、JavaScriptが無効になっているようです。

Get Adobe Flash player

スクロールバー

ソースコード

package 
{
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	
	/**
	 * スクロールバーのサンプル
	 * @author Hikipuro
	 */
	public class Main extends Sprite 
	{
		/**
		 * スクロールバーの現在の値
		 */
		private var value:int;
		
		/**
		 * スクロールバーの最大値
		 */
		private var maxValue:int;
		
		/**
		 * スクロールバーの左端の座標
		 */
		private var scrollMin:int;
		
		/**
		 * スクロールバーの右端の座標
		 */
		private var scrollMax:int;
		
		/**
		 * スクロールバー全体を指すスプライト
		 */
		private var scrollBar:Sprite;
		
		/**
		 * スクロールバーの背景の棒
		 */
		private var bgSprite:Sprite;
		
		/**
		 * スクロールバーのつまみ
		 */
		private var grabSprite:Sprite;
		
		/**
		 * 現在の値を表示するテキストフィールド
		 */
		private var textField:TextField;
		
		// ----------------------------------------------------------
		
		/**
		 * コンストラクタ
		 */
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		/**
		 * 初期化イベント
		 * @param	e
		 */
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			
			// スクロールバーの値設定
			value = 0;
			maxValue = 300;
			
			// スクロールバーの可動領域の座標設定
			scrollMin = 2;
			scrollMax = 200 - 2 - 20;
			
			// 現在の値表示用テキストフィールド初期化
			textField = new TextField();
			textField.autoSize = TextFieldAutoSize.CENTER;
			textField.selectable = false;
			textField.x = 160;
			textField.y = 120;
			addChild(textField);
			
			// スクロールバー作成 --------------------------------------------
			var g:Graphics;
			
			// スクロールバー全体のスプライトを登録
			scrollBar = new Sprite();
			scrollBar.x = 60;
			scrollBar.y = 100;
			addChild(scrollBar);
			
			// 背景の棒を登録
			bgSprite = new Sprite();
			bgSprite.x = 0;
			bgSprite.y = 10 - 2;
			scrollBar.addChild(bgSprite);
			
			// 背景の棒を描く
			g = bgSprite.graphics;
			g.lineStyle(1, 0x555555, 1.0, true);
			g.beginFill(0xddddff);
			g.drawRoundRect(0, 0, 200, 4, 4, 4);
			g.endFill();
			
			// つまみを登録
			grabSprite = new Sprite();
			grabSprite.x = 2;
			grabSprite.y = 0;
			scrollBar.addChild(grabSprite);
			
			// つまみを描く
			g = grabSprite.graphics;
			g.lineStyle(1, 0xdddddd, 1.0, true);
			g.beginFill(0x777777);
			g.drawCircle(10, 10, 10);
			g.endFill();
			// スクロールバー作成終了 ------------------------------------------
			
			// スクロールバーのつまみ用イベントの登録
			grabSprite.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			grabSprite.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			
			// ステージ全体でマウスのボタンが離された時のイベントの登録
			// - つまみの真上でマウスが離されなかった場合、ステージでマウスアップイベントを拾わないと
			//   stopDrag() が呼ばれなくなってしまうため
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			
			// フレーム開始イベントの登録
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		/**
		 * フレーム開始イベント
		 * @param	event
		 */
		private function onEnterFrame(event:Event):void
		{
			var ratio:Number;
			ratio = (grabSprite.x - scrollMin) / (scrollMax - scrollMin);
			value = ratio * maxValue;
			textField.text = value.toString();
		}
		
		/**
		 * スクロールバーのつまみが押された時
		 * @param	event
		 */
		private function onMouseDown(event:MouseEvent):void
		{
			var bounds:Rectangle = new Rectangle(scrollMin, 0, scrollMax - scrollMin, 0);
			grabSprite.startDrag(false, bounds);
		}
		
		/**
		 * スクロールバーのつまみが離された時
		 * @param	event
		 */
		private function onMouseUp(event:MouseEvent):void
		{
			grabSprite.stopDrag();
		}
		
	}
	
}		

GUI 部品の動作を直接メインのコード上に書くと、
このサンプルのように見にくくなってしまいます。

このままでは、どこまでが GUI の処理で、
どこまでがプログラムの進行に重要な処理なのか区別がつきません。

なので、GUI 部品は別クラスにして保存しておき、
メインのプログラムから import されるような
構造にした方が良いと思います。

GUI 部品のクラスは、動作の詳細については外部に公開せず、
変数値 (プロパティ) のセットによってその動作が決まるような構造にすると
見やすいコードになると思います。

参照

外部リンク