2

this question becomes hotについて話すとき、ボタンは最も人気のある GUI コンポーネントの 1 つですmemory usage。特にtons of buttonsアプリケーションにある場合。

では、使用するボタンを実装する方法minimum CPU and memory resourcesと、はい、マウスの上下と手のポインターの動作が実装された通常のボタンのように機能する方法を説明します。ラベル テキストも必要です。

4

4 に答える 4

3

最小量の RAM と処理能力を使用して、テキストとグラフィックスを備えた大量のボタンが必要な場合は、ビットマップを使用する必要があります。

これはさらに複雑になり、次のことを独自に準備する必要があります。

  1. スプライトシート形式のフォント。
  2. そのスプライト シートを使用してビットマップ上にテキストをレンダリングすることを管理するクラス。
  3. ビットマップは MouseEvents に応答しないため、ビットマップでのマウス入力を管理する独自のシステムを構築する必要があります。

最初に、最もよく使用されると思われるいくつかの DisplayObject のベース メモリ消費量を見てみましょう。これが私たちのテスト方法です:

function ram(type:Class):void
{
    trace(getSize(new type()));
}

そして、これはテストです:

ram(Sprite); // 408
ram(Shape); // 236
ram(TextField); // 1316

あなたの場合、1000 個のボタンを描画すると、1,724,000 バイト以上のメモリが使用されることになります。

次に、何を使用するかを見てみましょう。

  1. すべてのボタンを保持するキャンバスとして機能する 1x ビットマップ: 236 バイト。
  2. 各ボタンの初期状態を表す 1x BitmapData。
  3. 各ボタンのロールオーバー状態を表す 1x BitmapData。
  4. すべてのボタンで使用するスプライト シートとしてテキストを格納する 1x BitmapData。

それぞれBitmapDataのメモリ消費量は非常に大きく、その内容によって大きく異なります。しかし、ここでの秘訣は、描画するボタンごとに1 つだけを使用し、その内容を参照することです。

作業を開始できるように、少量のコードをセットアップしました。すべてのボタンをループし、クリックをトリガーするのに最も関連するものを見つけ出し、ボタンのテキストをレンダリングするクリック マネージャーを実装する必要があります。

ボタンクラスは次のとおりです。

public class BitmapButton
{

    private var _text:String;
    private var _position:Point = new Point();


    public function BitmapButton(text:String)
    {
        _text = text;
    }


    public function render(canvas:BitmapData, font:BitmapData, state:BitmapData):void
    {
        canvas.copyPixels(state, state.rect, _position);

        // Use font argument to render text.
        // For you to implement.
    }


    public function get position():Point{ return _position; }

}

これらのボタンのレンダリングを管理するクラスは次のとおりです。

public class ButtonCanvas extends Bitmap
{

    private var _fontSprite:BitmapData;
    private var _baseState:BitmapData = new BitmapData(100, 30, false, 0xFF0000);
    private var _overState:BitmapData = new BitmapData(100, 30, false, 0x00FF00);
    private var _buttons:Vector.<BitmapButton> = new <BitmapButton>[];
    private var _checkRect:Rectangle = new Rectangle();


    public function ButtonCanvas(width:int, height:int)
    {
        bitmapData = new BitmapData(width, height, true, 0x00000000);

        // Replace with actual loaded sprite sheet.
        _fontSprite = new BitmapData(1, 1);
    }


    public function add(button:BitmapButton):void
    {
        _buttons.push(button);
    }


    public function render():void
    {
        if(stage === null) return;

        bitmapData.lock();
        for each(var i:BitmapButton in _buttons)
        {
            _checkRect.x = i.position.x;
            _checkRect.y = i.position.y;
            _checkRect.width = _baseState.width;
            _checkRect.height = _baseState.height;

            if(_checkRect.contains(mouseX, mouseY))
            {
                // Use roll over style.
                // Need to implement depth check so you can't roll over buttons
                // that fall behind others.
                i.render(bitmapData, _fontSprite, _overState);
            }
            else
            {
                i.render(bitmapData, _fontSprite, _baseState);
            }
        }

        bitmapData.unlock();
    }


    public function get buttons():Vector.<BitmapButton>{ return _buttons; }

}

そして小さなテスト:

var canvas:ButtonCanvas = new ButtonCanvas(stage.stageWidth, stage.stageHeight);
addChild(canvas);


for(var i:int = 0; i < 20; i++)
{
    var button:BitmapButton = new BitmapButton("Hello");
    button.position.x = Math.random() * stage.stageWidth;
    button.position.y = Math.random() * stage.stageHeight;
    canvas.add(button);
}


stage.addEventListener(MouseEvent.MOUSE_MOVE, update);
function update(e:MouseEvent):void
{
    canvas.render();
}

canvas.render();

以上のことをすべて読んだので、ボタンを中心に展開する何らかのタイプのゲームがなく、ボタンが実際にはフレーム内のすべてのフレームで生成されるパーティクルでない限り、この極端な場所に近づく必要はほとんどないことを指摘します 100代。ほとんどの場合、標準の Sprite + TextField を使用してもまったく問題ありません。

于 2013-07-11T23:16:45.650 に答える
1

伝統的なパターンの1つはSprite + TextField

アドビでは、Sprite の代わりに Shape を使用することを推奨しています (意味がある場合)。

Sprite オブジェクトは表示オブジェクト コンテナですが、Shape オブジェクトはそうではありません。このため、Shape オブジェクトは、同じグラフィックスを含む Sprite オブジェクトよりも消費するメモリが少なくなります。

Shape を使用するのは素晴らしいことですが、それは可能ですが、それに TextField を追加することはできません。

次に、TextField 継承チェーンを見てみましょう。

TextField: InteractiveObject -> DisplayObject -> EventDispatcher -> オブジェクト

TextField オブジェクトは Sprite オブジェクトよりもはるかに軽量であることがわかりますが、これは間違いです。TextField のみを使用すると、 を使用するよりも軽くなりTextField + Spriteます。私はこの決定を思いつきました:

import flash.events.MouseEvent;
import flash.filters.BevelFilter;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.ui.Mouse;
import flash.ui.MouseCursor;

public class Button extends TextField 
{
    private static const MOUSE_UP:Array = 
    [new BevelFilter(2, 45, 0xEEEEEE, .7, 0x444444, .7, 1, 1)];

    private static const MOUSE_DOWN:Array = 
    [new BevelFilter(2, 225, 0xEEEEEE, .7, 0x444444, .7, 1, 1)];

    private static const TEXT_FORMAT:TextFormat = 
    new TextFormat('Verdana', 12, 0xDDDDDD,
    null, null, null, null, null, 'center');

    public function Button(label:String, color:int = 0x166488) 
    {
        width = 80;
        height = 20;
        background = true;
        backgroundColor = color;
        selectable = false;
        defaultTextFormat = TEXT_FORMAT;

        text = label;
        addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
        addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        addEventListener(MouseEvent.ROLL_OVER, onMouseRollOver);
        addEventListener(MouseEvent.ROLL_OUT, onMouseRollOut);
        onMouseUp();
    }

    private function onMouseRollOut(e:MouseEvent):void 
    {
        Mouse.cursor = MouseCursor.AUTO;
    }

    private function onMouseRollOver(e:MouseEvent):void 
    {
        Mouse.cursor = MouseCursor.BUTTON;
    }

    private function onMouseDown(e:MouseEvent):void 
    {
        filters = MOUSE_DOWN;
    }

    private function onMouseUp(e:MouseEvent = null):void 
    {
        filters = MOUSE_UP;
    }
    //kill method
}

生成されたボタン

このコードは素敵な軽量ボタンを描画ますが、テキストラベルの垂直位置を調整できないため、このボタンの高さはフォントサイズに依存します。もう 1 つの問題は、誰かがクリックしたときに、テキスト ラベルを少し右下に移動できないことです。

どんなアイデアでも大歓迎です。

于 2013-07-11T21:31:37.980 に答える
1

TextField オブジェクトは Sprite オブジェクトよりもはるかに軽いことがわかります。それは完全に間違っています。Sprite はメモリ内で 408 バイトを使用しますが、TextField は 1316 を使用します。

はい、TextField はより多くのメモリを消費します。

グラフィック プログラムでラベル テキストを作成し、スプライト メニュー クラスを作成します。

TextField はそれほど軽量ではありませんが、非常に強力なクラスです。ユーザー入力が必要な場合は、TextField が最適です。

Flash ライブラリに組み込まれているボタンは一切使用せず、スプライト クラスで単純な機能を構築するだけで開始します。

インターフェイスを本当に最適化したい場合は、イベント ハンドラーとあらゆる種類の透過性を減らします。これは、Flash に関する一般的なアドバイスですが、見過ごされがちです。

フレームごとに呼び出される関数を作成する、tick();、think();、update(); このようなもの。単一のイベント ハンドラーをメイン クラスに追加し、その中でメニュー要素内で update() 関数を呼び出します。

メニュー要素に多数のイベント ハンドラーを追加するのは、面倒なだけでなく見栄えも悪くなります。

于 2013-07-13T12:14:31.210 に答える