Flex 面板未更新
我正在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
可怕的是:
Flex 是单线程的,所以我认为你永远不会给 UIComponents 完全更新的机会。
替代方法是在计时器上运行绘制和更新方法,或者在
ENTER_FRAME
事件上运行它们。其中任何一个都会让显示列表更新发生在您的 之间,然后
或
Scary:
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 yourand then either of
or