2009-08-21 15 views
6

¿Cuál es la mejor forma de renderizar en un UIComponent que no se ha agregado al escenario? (Estoy usando UIComponents como renderizadores para objetos, y quiero renderizar nuevas copias para exportar, filtrar, etc.)Flex: ¿renderiza un UIComponent no realizado a BitmapData?

Dos estrategias que he visto/usado hasta ahora incluyen realizar el componente para asegurar que llame a todo el métodos de ciclo de vida:

  1. añadir el componente a Application.application, el procesamiento con BitmapData.draw(), eliminar el componente. Esto es similar a lo que he visto hacer para imprimir componentes no realizados también.

  2. Agregue el componente a una ventana emergente, renderice con BitmapData.draw(), cierre la ventana emergente una vez completada la representación.

Creo que ambos sólo se basan en la interfaz de usuario no refrescante, mientras que el hilo/evento actual se está ejecutando, aunque (1) también podría depender del componente de realizarse fuera de la vista.

¿Hay una manera mejor?

+0

¿Por qué necesita un UIComponent? ¿Necesitas interacciones de UI? Si solo necesitas dibujar algo, usa Sprite, es más liviano. – CookieOfFortune

Respuesta

10

Lo que yo he utilizado en el pasado con mucho éxito es la siguiente:

  1. crear una nueva instancia del componente
  2. añadir un detector de eventos para FlexEvent.CREATION_COMPLETE
  3. Conjunto visible = false en el componente
  4. Añadir el componente como un hijo de la aplicación principal
  5. Cuando se crea el componente, se invoca la función de detector de eventos. El resto de la lógica debe ingresarse/invocarse desde su función de escucha de eventos
  6. Eliminar el detector de eventos que agregó en el paso # 2.
  7. Use ImageSnapshot.captureImage() o captureBitmapData() para capturar la representación visual del componente.
  8. Eliminar el componente de la aplicación principal
  9. Procese los datos de la imagen como sea necesario.

Lo he usado para tomar instantáneas de varios componentes de gráficos Flex para su uso en PDF generados en el lado del servidor. Después de obtener el BitmapData, uso las clases PNGEncoder o JPEGEncoder para comprimir los datos, luego los codifico en Base64 antes de subirlos al servidor.

+0

Sólo una nota, es posible que desee buscar en PurePDF para hacer la generación del lado del cliente en lugar de servidor, pero depende de lo que esté haciendo. ¡Gran biblioteca! – JTtheGeek

2

Estoy bastante seguro de que puede usar el método draw() en BitmapData sin tener su componente en la Lista de visualización.

Por ejemplo, lo uso cuando necesito modificar las imágenes que cargo con la clase Loader. En el manejador de init creo una instancia de BitmapData y dibujo el mapa de bits desde la propiedad loadInfo.content, luego copyPixels() o lo que sea necesario para modificar la imagen cargada

+0

Puedes hacerlo, pero dado que el UIComponent no se ha realizado aún no se ha establecido. Entonces, como ejemplo, su altura y ancho son 0. –

+0

¡oh sí! Recuerdo algo sobre el componente que mide con los padres, dibujar niños, invalidar, etc. No he usado flex por un tiempo. ¿No puedes crear el componente, agregarlo a la lista de visualización, pero establecer visible a falso y continuar con el dibujo? –

1

Gran parte del diseño de UIComponent se puede vincular a su contexto. Esto es especialmente cierto para muchos de sus derivados (por ejemplo, HBox) ya que la fluidez del diseño está ligada al tamaño de sus padres y al número de hermanos que comparten el espacio de sus padres.

Además Flex puede ser un real dolor para actualizarse visualmente. A menudo, las funciones de renderizado críticas no se realizan de forma síncrona ... hay callLater, callLater2 y otros enfoques hacky que hacen que lidiar con las propiedades de diseño auto-mágico de UIComponents sean un gran dolor de cabeza. Ni siquiera llamar a validateNow o updateDisplayList puede garantizar que el diseño sea correcto en el fotograma actual (en lugar de unos pocos fotogramas en el futuro).

Sugiero que lo mejor que puedes hacer es no usar un UIComponent e intentar usar un Sprite u otro.

Su enfoque para adjuntarlo pero hacerlo invisible (alpha = 0, mouseEnabled = false, mouseChildren = false) es decente. Debe escuchar la devolución de llamada FlexEvent.CREATION_COMPLETE antes de estar seguro de que está correctamente distribuida. Luego puede bitmapData.draw y luego quitarlo del escenario. Si tiene que usar UIComponents entonces no conozco mejor manera.

0

Puede llamar a la función del ciclo de vida de forma manual antes de utilizar BitmapData.draw(). Haz lo siguiente.

  1. createChildren().
  2. commitProperties().
  3. updateDisplayList().
  4. bmd.draw().

Los primeros 2 pasos no son 100% necesarios, puede poner todos los códigos en updateDisplayList(). Debido a que invocas la función de forma manual, no tienes que preocuparte de que esto sea invocado por Flex framework muchas veces.

Cuestiones relacionadas