Flex 面板未更新

发布于 2024-08-15 20:58:50 字数 5392 浏览 4 评论 0原文

我正在 Flex Canvas 上绘制元胞自动机模拟。我交替计算自动机的状态和更新面板上的图形。然而,Panel的更新似乎并没有“跟上”CA状态的更新。

我想知道我对图形代码的处理是否做错了什么。代码如下。抱歉,它太长了,但我认为任何更简单的事情都不会出现问题(好吧,它可能会发生,但我不确定我是否想花时间找到它)。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init();">
    <mx:Script>
        <![CDATA[
        private static const universeRadius:uint = 8;

        private var universes:Array = new Array();
        private var currentUniverse:uint = 0;
        private var squareHeight:uint;
        private var squareWidth:uint;

        private function init():void {
            squareHeight = myCanvas.height / universeRadius;
            squareWidth = myCanvas.width / universeRadius;
            initUniverses();

            while (true) {
                trace("Calling draw()");
                draw();
                trace("Calling updateUniverse()");
                updateUniverse();
            }
        }

        private function initUniverses():void {
            var universe0:Array = new Array();
            var universe1:Array = new Array();

            var i:int;
            for (i = 0; i < universeRadius; i++) {
                var universe0Row:Array = new Array();
                var universe1Row:Array = new Array();
                var j:int;
                for (j = 0; j < universeRadius; j++) {
                    if (Math.random() < 0.5) {
                        universe0Row[j] = 0;
                    } else {
                        universe0Row[j] = 1;
                    }
                    universe1Row[j] = 0;
                }
                universe0[i] = universe0Row;
                universe1[i] = universe1Row;
            }

            universes[0] = universe0;
            universes[1] = universe1;
        }

        private function normalize(pos:int):int {
            return (pos + universeRadius) % universeRadius;
        }

        private function updateUniverse():void {
            var newUniverse:int = 1 - currentUniverse;
            var i:int;
            for (i = 0; i < universeRadius; i++) {
                var j:int;
                for (j = 0; j < universeRadius; j++) {
                    var dx:int;
                    var dy:int;
                    var count:int = 0;
                    for (dx = -1; dx <= 1; dx++) {
                        var neighborX:int = normalize(i + dx);
                        for (dy = -1; dy <= 1; dy++) {
                            var neighborY:int = normalize(j + dy);
                            if ((dx != 0 || dy != 0) && 
                                universes[currentUniverse][neighborX][neighborY] == 1) {
                                    count++;
                                }
                        }
                    }
                    var currentCell:int = universes[currentUniverse][i][j];
                    if (currentCell == 1) {
                        // 1. Any live cell with fewer than two live neighbours 
                        //    dies, as if caused by underpopulation.
                        if (count < 2) {
                            universes[newUniverse][i][j] = 0;
                        }
                        // 2. Any live cell with more than three live neighbours
                        //    dies, as if by overcrowding.
                        else if (count > 3) {
                            universes[newUniverse][i][j] = 0;
                        }
                        // 3. Any live cell with two or three live neighbours 
                        //    lives on to the next generation.
                        else {
                            universes[newUniverse][i][j] = 1;
                        }
                    } else {
                        // 4. Any dead cell with exactly three live neighbours 
                        //    becomes a live cell.
                        if (count == 3) {
                            universes[newUniverse][i][j] = 1;
                        } else {
                            universes[newUniverse][i][j] = 0;
                        }
                    }
                }
            }

            currentUniverse = newUniverse;
        }

        private function draw():void {
            myCanvas.graphics.clear();
            myCanvas.graphics.beginFill(0xFFFFFF, 1.0);
            myCanvas.graphics.drawRect(0, 0, myCanvas.width, myCanvas.height);
            var i:int;
            for (i = 0; i < universeRadius; i++) {
                var j:int;
                for (j = 0; j < universeRadius; j++) {
                    if (universes[currentUniverse][i][j] == "1") {
                        myCanvas.graphics.beginFill(0x000000, 1.0);
                        myCanvas.graphics.drawRect(
                            j * squareWidth, i * squareHeight, squareWidth, squareHeight)
                    }
                }
            }
            myCanvas.graphics.endFill();
        }
        ]]>
    </mx:Script>
    <mx:Panel title="Life" height="95%" width="95%" 
        paddingTop="5" paddingLeft="5" paddingRight="5" paddingBottom="5">

        <mx:Canvas id="myCanvas" borderStyle="solid" height="100%" width="100%">
        </mx:Canvas>
    </mx:Panel>
</mx:Application>

I am drawing a cellular automaton simulation on a Flex Canvas. I alternate computing the state of the automaton with updating the graphics on the Panel. However, the updating of the Panel does not seem to be "keeping up" with the update of the CA state.

I'm wondering whether I am doing something wrong with my handling of the graphics code. The code is below. Sorry it's so lengthy, but I don't think the problem will happen with anything simpler (well, it probably will, but I'm not certain I want to take the time to find it).

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init();">
    <mx:Script>
        <![CDATA[
        private static const universeRadius:uint = 8;

        private var universes:Array = new Array();
        private var currentUniverse:uint = 0;
        private var squareHeight:uint;
        private var squareWidth:uint;

        private function init():void {
            squareHeight = myCanvas.height / universeRadius;
            squareWidth = myCanvas.width / universeRadius;
            initUniverses();

            while (true) {
                trace("Calling draw()");
                draw();
                trace("Calling updateUniverse()");
                updateUniverse();
            }
        }

        private function initUniverses():void {
            var universe0:Array = new Array();
            var universe1:Array = new Array();

            var i:int;
            for (i = 0; i < universeRadius; i++) {
                var universe0Row:Array = new Array();
                var universe1Row:Array = new Array();
                var j:int;
                for (j = 0; j < universeRadius; j++) {
                    if (Math.random() < 0.5) {
                        universe0Row[j] = 0;
                    } else {
                        universe0Row[j] = 1;
                    }
                    universe1Row[j] = 0;
                }
                universe0[i] = universe0Row;
                universe1[i] = universe1Row;
            }

            universes[0] = universe0;
            universes[1] = universe1;
        }

        private function normalize(pos:int):int {
            return (pos + universeRadius) % universeRadius;
        }

        private function updateUniverse():void {
            var newUniverse:int = 1 - currentUniverse;
            var i:int;
            for (i = 0; i < universeRadius; i++) {
                var j:int;
                for (j = 0; j < universeRadius; j++) {
                    var dx:int;
                    var dy:int;
                    var count:int = 0;
                    for (dx = -1; dx <= 1; dx++) {
                        var neighborX:int = normalize(i + dx);
                        for (dy = -1; dy <= 1; dy++) {
                            var neighborY:int = normalize(j + dy);
                            if ((dx != 0 || dy != 0) && 
                                universes[currentUniverse][neighborX][neighborY] == 1) {
                                    count++;
                                }
                        }
                    }
                    var currentCell:int = universes[currentUniverse][i][j];
                    if (currentCell == 1) {
                        // 1. Any live cell with fewer than two live neighbours 
                        //    dies, as if caused by underpopulation.
                        if (count < 2) {
                            universes[newUniverse][i][j] = 0;
                        }
                        // 2. Any live cell with more than three live neighbours
                        //    dies, as if by overcrowding.
                        else if (count > 3) {
                            universes[newUniverse][i][j] = 0;
                        }
                        // 3. Any live cell with two or three live neighbours 
                        //    lives on to the next generation.
                        else {
                            universes[newUniverse][i][j] = 1;
                        }
                    } else {
                        // 4. Any dead cell with exactly three live neighbours 
                        //    becomes a live cell.
                        if (count == 3) {
                            universes[newUniverse][i][j] = 1;
                        } else {
                            universes[newUniverse][i][j] = 0;
                        }
                    }
                }
            }

            currentUniverse = newUniverse;
        }

        private function draw():void {
            myCanvas.graphics.clear();
            myCanvas.graphics.beginFill(0xFFFFFF, 1.0);
            myCanvas.graphics.drawRect(0, 0, myCanvas.width, myCanvas.height);
            var i:int;
            for (i = 0; i < universeRadius; i++) {
                var j:int;
                for (j = 0; j < universeRadius; j++) {
                    if (universes[currentUniverse][i][j] == "1") {
                        myCanvas.graphics.beginFill(0x000000, 1.0);
                        myCanvas.graphics.drawRect(
                            j * squareWidth, i * squareHeight, squareWidth, squareHeight)
                    }
                }
            }
            myCanvas.graphics.endFill();
        }
        ]]>
    </mx:Script>
    <mx:Panel title="Life" height="95%" width="95%" 
        paddingTop="5" paddingLeft="5" paddingRight="5" paddingBottom="5">

        <mx:Canvas id="myCanvas" borderStyle="solid" height="100%" width="100%">
        </mx:Canvas>
    </mx:Panel>
</mx:Application>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

二手情话 2024-08-22 20:58:50

可怕的是:

while (true) {

Flex 是单线程的,所以我认为你永远不会给 UIComponents 完全更新的机会。

替代方法是在计时器上运行绘制和更新方法,或者在 ENTER_FRAME 事件上运行它们。其中任何一个都会让显示列表更新发生在您的 之间

private function cycleUniverse(event:Event):void {
    updateUniverse();
    draw();
}

,然后

private var t:Timer;

private function init():void {
    t = new Timer(500); // every 500 ms
    t.addEventListener(TimerEvent.Timer, cycleUniverse);
    t.start();
}

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" enterFrame="cycleUniverse(event)">

Scary:

while (true) {

Flex is single-threaded, so I think you're never giving the UIComponents a chance to fully update.

Alternatives would be to run the draw and update methods on a Timer, or run them on the ENTER_FRAME event. Either of these would let the display list updates occur in between your

private function cycleUniverse(event:Event):void {
    updateUniverse();
    draw();
}

and then either of

private var t:Timer;

private function init():void {
    t = new Timer(500); // every 500 ms
    t.addEventListener(TimerEvent.Timer, cycleUniverse);
    t.start();
}

or

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" enterFrame="cycleUniverse(event)">
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文