2015-04-29 1 views
5

S'il vous plaît considérer ce simple code rebol2 pour illustrer mon problème:volet de mise en page VID supportant plusieurs créations face [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 
     ] 
    ] 
] 

Le point principal est ici pour une mise en page (ou face) pour être en mesure d'afficher un groupe de faces à l'intérieur de son bloc de manière à ce que plusieurs créations de la même face (b dans ce cas) soient possibles. Le code indiqué fonctionne bien, et le seul instance (laissez-moi l'appeler de cette façon) de b est affiché comme il se doit.

Mais Supposons maintenant que je changer le code, donc je l'ai, disons, 2 cas de b:

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

A ce stade, je reçois l'erreur

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

Du message que je présume ici, ce visage est en quelque sorte être réutilisé et déconner exactement ce que j'essaie d'atteindre. J'ai fait beaucoup de recherches à ce sujet et à un moment donné, j'ai trouvé qu'il est possible de contourner le problème en clonant (en utilisant make) le visage à passer à pane; c'est ce que je pensais faire, mais sans succès du tout. Étant donné ce scénario, ma question est la suivante: comment puis-je résoudre ce problème? est rebol2 ok pour fournir cette "face-instantiation" ou il est préférable d'essayer quelque chose d'autre en dehors de rebol2 (peut-être rebol3)?

Toute aide sera grandement appréciée.

Répondre

1

Comme déjà signalé le problème est que a est réutilisée, pas b!

La fonction de mise en page utilise un champ appelé init pour gérer ce type de choses. Si je comprends bien init est d'abord lié à la face, puis appelé avec do après que le visage lui-même est instancié (au moins partiellement).

Dans ce cas, je serais en utilisant la commande style dans la mise en page (toujours en utilisant partiellement l'objet face à 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'autre alternative, un peu plus proche de votre serait:

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 ] 
      ] 
     ] 
    ] 
] 

Notez que init est appelé manuellement dans la clause make dans ce cas. Je ne suis pas tout à fait sûr pourquoi c'est nécessaire. Enfin, le tout pourrait être résolu avec élégance dans un style

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

La deuxième approche fonctionnait mieux pour mon problème et elle était simple/transparente pour ce que j'avais l'intention de construire avec ce code. Merci de poster: D – rdonatoiop

3

Rebol2 est certainement autorisé à le faire.

Lorsque vous faites b pour la deuxième fois, vous utilisez la même instance de a. C'est le problème.

Vous pouvez écrire une fonction qui crée les faces nécessaires et les ajouter à un bloc et les renvoyer. N'oubliez pas de créer 'a (premier visage) à chaque fois.

De plus, vérifiez les faces itérées dans la documentation.

Ici, j'ajouté un exemple:

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] 
    ] 
] 

Vous pouvez modifier la fonction pour obtenir plus de paramètres à changer de couleur et d'autres aspects aussi bien.

+0

Merci pour l'exemple de code et pour les grandes idées, en particulier sur les visages itérées. Je suis en train de regarder ceux qui, d'après ce que j'ai lu jusqu'à présent, me conviennent un peu mieux. J'ai l'intention de jouer un peu autour et ensuite retourner n'importe quel code que j'ai écrit dans un poste de réponse pour le partage de la recherche. Merci encore: D – rdonatoiop

+1

Les visages itératifs sont un peu difficiles à utiliser et il n'y a pas assez de documentation à ce sujet. Mais il est utile pour les éléments d'interface utilisateur de style grille/table. – endo64

+0

désolé, endo64; J'ai changé ma réponse acceptée, bien que votre réponse me fournisse de bonnes idées. – rdonatoiop

0

J'ai dit sur un commentaire que je reviendrais pour partager mes conclusions et je pense que j'ai quelque chose d'intéressant. Comme l'a souligné @ endo64, les visages itérés sont difficiles et ne sont peut-être pas les mieux adaptés à ce que j'avais l'intention de faire lorsque j'ai posé la question pour obtenir une méthode simple/directe d'instanciation d'objets à travers des panneaux.

Je suis venu avec le code ci-dessous, qui implémente une sorte de instantiator. Il a été inspiré en partie par l'approche face-maker de @ endo64 avec quelques bricolages avec des visages itérés. Ce instantiator a une limitation principale, qui n'accepte pas plusieurs types d'objets transmis au constructeur pour être créé dans le même volet.

Quoi qu'il en soit, j'ai trouvé que c'était un exercice intéressant et je voudrais le poster ici au cas où il pourrait être utile à quelqu'un.


J'utilise le même code de la question, la résolution/contournent maintenant la limitation de créer plusieurs b objets à l'intérieur du volet de mise en page principale. a et b maintenant contenir un objet instantiator, qui reçoit un objet à créer à l'intérieur de son volet et un bloc de positions (paire de décalages) où les objets doivent être placés.

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 
] 

Le code de instantiateur est:

_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 
      ] 
     ] 
    ] 
] 

Code pour la mise en page principale est:

_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