2015-04-29 7 views
5

Si prega di considerare questo codice rebol2 semplice per illustrare il mio problema:VID riquadro layout di supportare molteplici creazioni del viso [rebol2]

REBOL [] 
a: make face [ 
    offset: 0x0 
    color: yellow 
    size: 20x20 
] 
b: make face [ 
    offset: 0x0 
    color: red 
    size: 60x60 
    pane: reduce [ 
     make a [offset: 0x0] 
     make a [offset: 10x10] 
     make a [offset: 10x20] 
    ] 
] 
view layout [ 
    box 200x200 white with [ 
     pane: reduce [ 
      make b [offset: 0x30] ;; one 'instance' of b 
     ] 
    ] 
] 

Il punto principale qui è per un layout (o faccia) per essere in grado di visualizzare un mucchio di facce all'interno del relativo riquadro in modo che siano possibili più creazioni della stessa faccia (b in questo caso). Il codice mostrato funziona bene e l'istanza (chiamiamola in questo modo) di b viene visualizzata come dovrebbe essere.

Ma ora supponiamo che io modificare il codice in modo che ho, diciamo, 2 casi di b:

view layout [ 
    box 200x200 white with [ 
     pane: reduce [ 
      make b [offset: 0x30] 
      make b [offset: 0x10] 
     ] 
    ] 
] 

A questo punto ho l'errore

** Script Error: Face object reused (in more than one pane): none 
** Where: view 
** Near: show scr-face 
if new [do-events] 

Dal messaggio presumo qui che faccia b è in qualche modo riutilizzato e incasinato esattamente quello che sto cercando di ottenere. Ho fatto molte ricerche al riguardo e ad un certo punto ho scoperto che è possibile aggirarlo clonando (usando make) il volto da passare a pane; questo è quello che pensavo di fare, ma senza successo.

Dato questo scenario, la mia domanda è: come posso andare a risolvere questo? è rebol2 ok per fornire questo "face-instantiation" o è meglio provare qualcos'altro al di fuori di rebol2 (forse rebol3)?

Qualsiasi aiuto sarà molto apprezzato.

risposta

1

Come già sottolineato il problema è che a viene riutilizzato, non b!

la funzione di layout utilizza un campo chiamato init per la gestione di cose come questa. A quanto ho capito, init viene prima associato alla faccia e quindi chiamato con do dopo l'istanza del volto stesso (almeno parzialmente).

In questo caso sarebbe utilizzando il comando style nel layout (ancora parzialmente utilizzando oggetto faccia a)

view layout [ 
    style 
     bb box 60x60 
     with [ 
      append init [ 
       pane reduce [ 
        make a [offset: 0x0] 
        make a [offset: 10x10] 
        make a [offset: 10x20] 
       ] 
      ] 
     ] 
    panel 200x200 white [ 
     at 30x0 bb 
     at 0x0 bb 
    ] 
] 

L'altra alternativa, un po 'più simile al vostro sarebbe:

b: make face [ 
    offset: 0x0 
    color: red 
    size: 60x60 
    init: [ 
     pane: reduce [ 
      make a [offset: 0x0] 
      make a [offset: 10x10] 
      make a [offset: 10x20] 
     ] 
    ] 
] 
view layout [ 
    box 200x200 
    with [ 
     append init [ 
      pane: reduce [ 
       make b [ offset: 0x0 do init ] 
       make b [ offset: 0x60 do init ] 
      ] 
     ] 
    ] 
] 

Si noti che init viene chiamato manualmente all'interno della clausola make in questo caso. Non sono del tutto sicuro del motivo per cui è necessario. Infine, il tutto potrebbe essere risolto elegantemente con lo stile

view layout [ 
    style a box yellow 20x20 
    style b panel red 60x60 [ 
     at 0x0 a ; we can in this style use the just defined a style 
     at 10x10 a 
     at 10x20 a 
    ] 
    at 0x0 b 
    at 0x60 b 
] 
+0

Il secondo approccio ha funzionato meglio per il mio problema ed è stato semplice e trasparente per ciò che intendevo sviluppare in seguito con questo codice. Grazie per la pubblicazione: D – rdonatoiop

3

Rebol2 è decisamente ok per farlo.

Quando si esegue b la seconda volta si utilizza la stessa istanza di a. Quello è il problema.

È possibile scrivere una funzione che crea le facce necessarie e le aggiunge a un blocco e restituisce. Non dimenticare di creare 'una (prima faccia) ogni volta.

Inoltre, controllare i volti iterati nella documentazione.

Qui ho aggiunto un esempio:

REBOL [] 
make-pane: func [ofst [pair! block!] /local a b faces] [ 
    a: make face [ 
     offset: 0x0 
     color: yellow 
     size: 20x20 
    ] 
    faces: copy [] 
    either block? ofst [ 
     foreach o ofst [ 
      append faces make a [offset: o] 
     ] 
    ] [ 
     append faces make a [offset: ofst] 
    ] 
    b: make face [ 
     offset: 0x0 
     color: red 
     size: 60x60 
     pane: faces 
    ] 
] 

view layout [ 
    box 200x200 white with [ 
     pane: make-pane [5x30 0x10 20x5] 
    ] 
] 

È possibile modificare la funzione per ottenere più parametri a cambiare colore e altri aspetti pure.

+0

Grazie per il codice di esempio e per le grandi intuizioni, specialmente sui volti iterate. Attualmente sto esaminando quelli, che penso (da quello che ho letto finora) mi va un po 'meglio. Intendo giocare un po 'e poi restituire qualsiasi codice che ho scritto in un post di risposta per motivi di condivisione della ricerca. Grazie ancora: D – rdonatoiop

+1

I visi ripetuti sono un po 'difficili da usare e non c'è abbastanza documentazione su di esso. Ma è utile per gli elementi dell'interfaccia utente stile griglia/tabella. – endo64

+0

scusate, endo64; Modificata la mia risposta accettata, anche se la tua risposta mi ha fornito grandi spunti. – rdonatoiop

0

Ho detto in un commento che sarei tornato per condividere le mie scoperte e penso di avere qualcosa di interessante. Come sottolineato da @ endo64, le facce iterate sono complicate e forse non sono le più adatte a quello che intendevo fare quando ho posto la domanda per ottenere un modo semplice/stravagante per istanziare oggetti attraverso i pannelli.

Mi è venuto in mente il codice muggito, che implementa una specie di istanzatore . È stato in parte ispirato dall'approccio face-maker di @ endo64 e da alcuni ritocchi con facce iterate. Questo istanziatore ha una limitazione principale, che non accetta più tipi di oggetti passati al costruttore da creare nello stesso riquadro.

In ogni caso, ho trovato che era un esercizio interessante e mi piacerebbe postarlo qui nel caso in cui potrebbe essere utile a qualcuno.


uso lo stesso codice dalla domanda, ora risolvendo/aggirare la limitazione di creazione di più b oggetti all'interno del riquadro di estensione principale. a e b ora contengono un oggetto instantiator, che riceve un oggetto da creare all'interno del riquadro e un blocco di posizioni (coppie di offset) in cui posizionare gli oggetti.

a: make face [ 
    offset: 0x0 
    color: yellow 
    size: 30x20 
] 

b: make face [ 
    offset: 0x0 
    color: red 
    size: 100x100 
    inst_b: _instantiator/new reduce a [10x10 10x70 80x80 30x30] ; instantiator here 
    pane: get in inst_b 'pane_function 
] 

Il codice instantiator è:

_instantiator: make object! [ 
    _obj: copy [] 
    _offsets: copy [] 

    new: func [ 
     obj [object!] "object to create inside pane" 
     offs [block!] "instances offsets" 
    ][ 
     make self [ 
      _obj: obj 
      _offsets: offs 
     ] 
    ] 
    pane_function: func [face index] [ 
     if integer? index [ 
      if index <= length? _offsets [ 
       _obj/offset: to-pair reduce [_offsets/:index/x _offsets/:index/y] 
       _obj 
      ] 
     ] 
    ] 
] 

codice per il layout principale è:

_inst: _instantiator/new reduce b [0x0 50x50 130x130] ;;3 b objects are created in the positions indicated in the pairs block 
_lo: layout [ 
    mybox: box 500x500 white with [ 
     offset: 0x0  
     pane: get in _inst 'pane_function 
    ] 
] 
view center-face _lo 
Problemi correlati