2010-01-22 8 views
9

Tengo un pequeño problema con mi evento de cambio de tamaño ... Creé un componente yo mismo, y este componente, en cada evento de cambio de tamaño, ejecuta un método complejo. Aquí está el problema: cuando maximizo o restauro mi ventana, este evento se llama varias veces en un período de tiempo muy corto, sin dejar tiempo suficiente para que mi método se ejecute completamente antes de que comience otro ... Me gustaría saber si de todos modos solo se ejecuta este método al final de cada movimiento de cambio de tamaño. GraciasFlex - Problema con ResizeEvent.RESIZE

Respuesta

20

En lugar de reaccionar a un ResizeEvent, que disparará cada fotograma durante un cambio de tamaño (es decir, si maximiza y tarda 3 fotogramas para que el componente vuelva a dibujarse de widh/ehight = 0 a width/height = MaxValue), entonces El evento de cambio de tamaño disparará tres veces, podría "mirar" las propiedades de ancho y alto.

var widthWatch:ChangeWatcher = ChangeWatcher.watch(this, 'widht', resizeHandler) 
var heightWatch:ChangeWatcher = ChangeWatcher.watch(this, 'height' resizeHandler) 

esta voluntad, en efecto, observar las propiedades, similares a enlace de datos, y ejecutar su resizeHandler siempre que la anchura o la altura de cambio. Esto tiene un pequeño inconveniente en disparar tu controlador dos veces si el ancho y el alto cambian al mismo tiempo, pero eso se puede resolver con una tercera función que hace el trabajo, que los manejadores invocan si no se invoca el horario. . El código:

<?xml version="1.0" encoding="utf-8"?> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="onCreationComplete(event)"> 
<mx:Script> 
<![CDATA[ 
    import mx.binding.utils.ChangeWatcher; 

    private var widthWatch:ChangeWatcher; 
    private var heightWatch:ChangeWatcher; 
    private var resizeExecuting:Boolean = false; 

    private function onCreationComplete(event:Event):void 
    { 
    widthWatch = ChangeWatcher.watch(this,'width',onSizeChange); 
    heightWatch = ChangeWatcher.watch(this,'height',onSizeChange); 
    } 

    private function onSizeChange(event:Event):void 
    { 
    if(!resizeExecuting) 
    callLater(handleResize); 
    resizeExecuting = true; 
    } 

    private function handleResize():void 
    { 
    //do expensive work here 
    resizeExecuting = false; 
    } 

    private function stopWatching() 
    { 
    //invoke this to stop watching the properties and prevent the handleResize method from executing 
    widthWatch.unwatch(); 
    heightWatch.unwatch(); 
    } 

]]> 
</mx:Script> 
</mx:Application> 

Yo prefiero el método de cambio de observador porque se dispara al cabo las propiedades de anchura y altura han cambiado, a diferencia de un evento de cambio de tamaño incendios wich antes de que las propiedades de anchura y altura se actualizan correclty.

+0

esto es realmente genial, ¡gracias por compartir esto! – D3vtr0n

+1

como complemento de esto, ya que experimenté este problema mucho con nuestros componentes de gráficos en Dedoose, para romper su compleja operación con greenthreading (http://code.google.com/p/greenthreads/). Mantenga un control sobre su actual GreenThread, y si no está completo, puede detenerlo a mitad del proceso para reiniciar. Esto permite una gran capacidad de respuesta de la interfaz de usuario y el tratamiento de cálculos complejos al redimensionar al mismo tiempo. – JTtheGeek

+0

Esto fue realmente útil, gracias. – ggkmath

3

Querrá unir los eventos de cambio de tamaño en un solo evento. David Coletta habló brevemente sobre el evento que se fusiona en this presentation, pero no recuerdo si describió cómo lo hizo.

Usted podría hacer esto de varias maneras, una de las cuales voy a Disposición en pseudo código a continuación:

resizeHandler(resizeEvent): 
    if (resizeEventReceived) 
     return 
    resizeEventReceived = true 
    Timer.startIn(30 /*ms*/).withHandler(doResize) 

doResize(timerEvent): 
    /* do actual resize processing */ 
    resizeEventReceived = false 
1

Me suena como si estuvieras haciendo algo en el controlador de eventos que está causando un nuevo ResizeEvent.RESIZE para ser disparado. Como ActionScript se ejecuta en un solo subproceso, no es posible que ningún origen independiente distribuya ese evento mientras el controlador se está ejecutando a menos que de alguna manera lo active.

1

me gustaría señalar que flex tiene un ciclo de vida del componente completo que podría ayudarle a:

Prueba esto:

  1. no calcular directamente su pantalla cambia, pero hacer esto en el método updateDisplayList .
  2. Al recibir la ResizeEvent, solamente llamar al método invalidateDisplayList(), que establece un indicador marco que dará lugar a la ejecución de updateDisplayList()

Puede leer más sobre el ciclo de vida Flex3 Componente aquí: http://www.dlgsoftware.com/primers/Primer_on_Flex3_Component_Lifecycle.htm