AS3:确定何时最终显示可显示对象

时间:2011-04-07 20:31:53

标签: flex actionscript-3 image

我希望确定可以确定已向用户呈现Image或UIComponent的最终事件或位置。我需要知道它何时被显示,因此,假设它没有被遮盖或者在一个愚蠢的位置,用户可以看到。

UpdateComplete Event Documentation中说:

  

这是在显示组件之前更改组件的最后机会。所有属性都已提交,组件已经过测量和布局。

覆盖Image上的dispatchEvent表明UpdateComplete事件是在更新.source属性后调度的最后一个事件。在该事件之后断开并遍历代码表明LayoutManager似乎在显示图像之前完成了它的操作。

我在canvas容器上观察了dispatchEvent和updateDisplayList,没有骰子。

我假设有一些更高(更低)的对象,我可以扩展或听取,这将给我最后一条信息。

请帮助。

===============================================

编辑:添加测试应用程序的代码示例

===============================================

NoisyImageTest.mxml - 用于观察事件循环的测试应用程序。如果您在第22行断点,则会看到最后一次更新完成事件,但图像尚未显示。从那里单步执行代码,它在LayoutManager之后退出线程,但仍然没有更新屏幕。我假设有一个点,系统管理器或阶段或其他项目可以说它绘制图像。这就是我要找的东西。

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:local="*">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>
    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;
            private var imagePointer : NoisyImage;

            private function onImageLoadClick( event : MouseEvent ) : void
            {
                //start loading the image
                canvasTarget.removeAllChildren();
                imagePointer = new NoisyImage();
                imagePointer.addEventListener(FlexEvent.UPDATE_COMPLETE, onUpdateComplete);
                canvasTarget.addChild( imagePointer );
                imagePointer.source = 'http://helios.gsfc.nasa.gov/image_euv_press.jpg';
            }  

            private function onImageLoadClick2( event : MouseEvent ) : void
            {
                if ( imagePointer )
                {
                    imagePointer.source = 'http://helios.gsfc.nasa.gov/30dor_qdw_big.gif';
                }
            }

            private function onUpdateComplete( event : FlexEvent ) : void
            {
                trace('percentLoaded ' + ( event.target as NoisyImage ).percentLoaded );
                trace('bytesLoaded ' + ( event.target as NoisyImage ).bytesLoaded );
                trace('content ' + ( event.target as NoisyImage ).content );
                if ( event.target.source )
                {
                    trace('onUpdateComplete has valid source.');
                    if ( event.target.width )
                    {
                        trace('onUpdateComplete has valid width.');                    
                    }
                }

            }             
        ]]>
    </fx:Script>
    <local:NoisyCanvas id="canvasTarget" width="500" height="400" horizontalCenter="0" />
    <mx:Button label="load image" click="onImageLoadClick(event)" horizontalCenter="0" />
    <mx:Button label="sticth source to image2" click="onImageLoadClick2(event)" horizontalCenter="0" />
</s:Application>

NoisyCanvas.as - 这是将放置noisyImage的画布,提供调度事件的所有痕迹

package
{
    import flash.events.Event;

    import mx.containers.Canvas;

    public class NoisyCanvas extends Canvas
    {
        public function NoisyCanvas()
        {
            super();
        }

        override public function dispatchEvent(event:Event):Boolean
        {
            trace( 'c dispatchEvent: ' + event );
            return super.dispatchEvent(event);
        }

        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {
            trace( 'c updateDisplayList: ' + unscaledWidth + ' ' + unscaledHeight );
            super.updateDisplayList(unscaledWidth, unscaledHeight);
        }

        override protected function childrenCreated():void
        {
            trace( 'c childrenCreated' );
            super.childrenCreated();
        }        
    }
}

NoisyImage.as - 这是提供调度事件所有痕迹的图像

package
{
    import flash.events.Event;

    import mx.controls.Image;

    public class NoisyImage extends Image
    {
        public function NoisyImage()
        {
            super();
        }

        override public function dispatchEvent(event:Event):Boolean
        {
            trace( 'i dispatchEvent: ' + event );
            return super.dispatchEvent(event);
        }

        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {
            super.updateDisplayList(unscaledWidth, unscaledHeight);
            trace( 'i updateDisplayList: ' + unscaledWidth + ' ' + unscaledHeight );
        }        
    }        
}

1 个答案:

答案 0 :(得分:0)

好吧....我以为我有一个解决方案。不幸的是,我真的不知道flex,但我可以提供我创建的Blitting类。

我希望您可以使用这些(或者至少是封装的想法)来找到可以帮助您的解决方案。我相信它是可能的 - 我只是不知道Flex对象是否足以实现它。

另外,请注意,这些课程是为我正在尝试制作的游戏而创建的,因此请随意删除任何您不需要的游戏。还有一些未完成的方法。这有点草率。 : - \

// Oh, and, please ignore my code comments, I tend to talk to myself.

类BLOB是许多这些类的基础对象,由bitmapData对象组成。 rect和point变量用于我的copyPixels操作;您可以从对象中提取这些值。

package com.lunchmeat317.blitter
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    /**
     * ...
     * @author lunchmeat317
     */
    public class BLOB
    // BLOB stands for BLit OBject.
    {
        // These are the core variables of this class. Debating whether to make these
        // internal or protected. Protected is logical, but are getters slower for
        // parsing?

        internal var data:BitmapData;
        internal var rect:Rectangle;
        internal var point:Point;

        // To be used with scrollrect in order to animate frames. Frameoffset...shit.
        // Do I pull these values from rect.width and rect.height? Is this necessary?
        // Maybe I should just make these booleans? Perhaps these value can be the
        // quotient of the rect dims from the bitmap dims? No idea. (That could help
        // with wrapping.)
        private var frameoffset:uint;

        // Variable that determines whether to blit this object or not. Blitting engine
        // will check this condition for each object it blits. True by default.
        private var visible:Boolean;

        public function BLOB(width:uint, height:uint, x_pos:int, y_pos:int, x_rectpos:uint, y_rectpos:uint, image:BitmapData)
        {
            data = image;
            rect = new Rectangle(x_rectpos, y_rectpos, width, height);
            point = new Point(x_pos, y_pos);

            visible = true;

            data.lock();
        }

        public function setVisibleState(value:Boolean):void
        {
            visible = value;
        }

        public function getVisibleState():Boolean
        {
            return visible;
        }

        public function setLocation(location:Point):void
        {
            point = location;
        }

        public function getLocation():Point
        {
            return point;
        }

        public function move(dx:Number, dy:Number):void
        {
            point.offset(dx, dy);
        }
    }
}

类BlitLayerCanvas基本上是bitmapData,您可以copyPixels()单个位图,但它不会出现在屏幕上,因为它没有添加到displaylist中。希望,查看此类将帮助您将对象复制到存储在内存中但不显示的画布上。 (提示:如果您知道不打算将其添加到displaylist中,则实际上不需要使用Bitmap容器类。)

package com.lunchmeat317.blitter
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.geom.Point;
    import flash.geom.Rectangle;

    /**
     * ...
     * @author lunchmeat317
     */
    public final class BlitLayerCanvas extends BLOB
    {
        public var bloblist:Vector.<BLOB>;

        public function BlitLayerCanvas(width:uint, height:uint, x_pos:int, y_pos:int, x_rectpos:uint, y_rectpos:uint)
        {
            super(width, height, x_pos, y_pos, x_rectpos, y_rectpos, new BitmapData(width, height, true, 0x0));

            bloblist = new Vector.<BLOB>();
        }

        public function addObject(obj:BLOB):void
        {
            bloblist.push(obj);
            trace("BLOB added to bloblist");
        }

        public function update():void
        {
            for each (var x:BLOB in bloblist)
            {
                data.copyPixels(x.data, x.rect, x.point, null, null, true);
            }
        }

        public function flush():void
        {
            data.fillRect(data.rect, 0x0);
        }
    }
}

还有两个类,但它们几乎是相同的概念 - 一个没有画布的图层类(基本上是BLOB的矢量)和更新屏幕的最终类。他们的工作方式相同。

我知道这很少,我希望我能提供更多信息。这肯定不是世界上最好的答案,但我希望我的代码片段至少可以让你指向正确的方向。如果您有任何问题,请告诉我,我会尽力回答。

祝你好运。