Generación y uso dinámico de multiples objetos

Antes de adentrarnos en cuestiones más puntuales, en este apartado aboradaré una opción que debería tenerse en cuenta a la hora de generar determinadas configuraciones de objetos en una aplicación para permitir un desarrollo abierto.

Sea, por ejemplo, el caso de crear un tablero en el que disponer una actividad o un juego basados en casillas. Si se quiere disponer de un número elevado de objetos o que en tiempo de ejecución se determine la cantidad de estos, será necesario dejar que el código se ocupe de esta situación.

Sea, pues, el caso de un tablero (la Figura 6-2 muestra un base de experimentación de este supuesto) sobre el que se dispondrán una serie de elementos y sobre los que el usuario deberá actuar.

Figura 6-2. Ejemplo de construcción dinámica de interfaz.

En este ejemplo, a la derecha, se ha dispuesto un grupo de objetos que permiten la construcción de este tablero basado en botones. Este grupo puede quedar oculto en una determinada aplicación, pero la funcionalidad del ejemplo sigue siendo la misma.

Con este ejemplo, se puede crear de forma dinámica una serie de botones. El número y tamaño de los mismos se indica en los controles situados en el mencionado grupo.

La mayor parte de la funcionalidad de este ejemplo reside en el botón que, a partir de los valores de los restantes elementos inicializa y dipone los botones en la ventana (la pila, en terminología de MetaCard) cuando el usuario lo activa. Su código es el siguiente:

button "Fer-lo"
on mouseUp
  repeat with i = the number of buttons down to 1
    if the short name of button i contains "boto" then delete button i
  end repeat
  
  repeat with i = 0 to ((field "nFiles" * field "nCols") - 1)
    lock messages
    create invisible button ("boto" & i)
    unlock messages
    
    set the height of button ("boto" & i) to field "altCuadre"
    set the width of button ("boto" & i) to field "ampleCuadre"
    show button ("boto" & i)
    
    move  button ("boto" & i) \
        to ( ((field "ampleCuadre") * (i mod field "NCols")) + round(field "ampleCuadre" / 2) ), \
        ( (field "altCuadre" * trunc(i / field "NCols")) + round(field "altCuadre" / 2) ) \
        in 0.5 seconds
  end repeat
end mouseUp
             

Sugerencia: Se podría haber hecho de forma estática con

set the location of button ... to ...
y lo dejo propuesto para que participe y repase lo que se ha tratado al respecto de esta orden con anterioridad. Aunque, espero que estará conmigo en que el resultado final es más divertido con la orden move.

Para facilitar la oportunidad visual que ofrece este interfaz, los campos de texto que configuran el tamaño de los botones creados modifican el del botón que desencadena toda la acción con el código siguiente, que se ejecutan cuando se teclea un valor numérico en los campos asociados:

#field "ampleCuadre"
on keyUp tecla
  set the width of button "Fer-lo" to the text of me
end keyUp


#field "altCuadre"
on keyUp tecla
  set the height of button "Fer-lo" to the text of me
  set the top of button "Fer-lo" to (the bottom of me + 10)
end keyUp
             

Aviso

En concret gràfics, en les equacions de curves i demés que preparares per a la figura de la portà.

#
# btn "ferLaEspiral"
#
on mouseUp
  
  put empty into varAux
  put round(the first item of the loc of this card)  into despAlCentroX
  put round(the second item of the loc of this card) into despAlCentroY
  
  -- Ecuacio d'una espiral? No la se, pero es com un circul que es va obrint poc a poc
  -- Si no mes que vols que pegue una volta ...
  put round (360 / the number of lines of fld "nomsDeImages") into grausPerPunt
  put round (despAlCentroY * 2  / the number of lines of fld "nomsDeImages") into incrRadioX
  -- I ara mira de calcular els punts
  repeat with i = 0 to (the number of lines of fld "nomsDeImages"  - 1)
    --    put (i * incrRadio) into radio
    put  (round( sin( pi / 180 * (i * grausPerPunt) ) * (i * incrRadioX ) ) + despAlCentroX) &\
        "," &\
        (round( cos( pi / 180 * (i * grausPerPunt) )  * (i * incrRadioX / 2) ) + despAlCentroY) &\
        return after varAux
    set the points of graphic "espiral" to varAux
  end repeat
end mouseUp

#
# btn "ficarLesImages"
#
on mouseUp
  put the points of graphic "espiral" into puntsEspiral

  repeat with i = the number of lines of fld "nomsDeImages" down to 1
    if not( the first char of (line i of fld "nomsDeImages") is "-" )
    then
      lock messages
      create image ("miniatura" & i)
      set the loc of image ("miniatura" & i) to line i of puntsEspiral

      set the filename of image ("miniatura" & i) to \
            (fld rutaImagens & line i of fld "nomsDeImages")
      
      put  the height of image ("miniatura" & i)  & "x" & the width of image ("miniatura" & i)
                 
      set the width of image ("miniatura" & i) to\
          ( the width of image ("miniatura" & i) / \
            (the height of image ("miniatura" & i) / 150))
      set the height of image ("miniatura" & i) to 150
      
      unlock messages
    end if
  end repeat
end mouseUp
             

Figura 6-3. Ejemplo de construcción dinámica de un gráfico y de objetos de tipo image superpuestos a aquel.