2015-04-29 7 views
5

Пожалуйста, обратите внимание этот простой код rebol2, чтобы проиллюстрировать мою проблему:VID расположение панели поддерживает несколько творений лица [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 
     ] 
    ] 
] 

Главное здесь для макета (или лица), чтобы иметь возможность отображать кучу граней внутри его панельного блока таким образом, чтобы в этом случае было возможно многократное создание одной и той же грани (b). Показанный код работает хорошо, и только экземпляр (позвольте мне назвать его таким образом) b отображается так, как должно быть.

Но теперь предположим, что я изменить код так, у меня есть, скажем, 2 экземпляры из b:

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

На данный момент я получаю ошибку

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

Из сообщения я предполагаю здесь, что лицо b каким-то образом получает повторное использование и возится именно с тем, чего я пытаюсь достичь. Я провел много исследований по этому вопросу, и в какой-то момент я обнаружил, что можно обойти его, клонируя (используя make) лицо, которое должно быть передано pane; это то, что я думал, что я делаю, но безуспешно.

Учитывая этот сценарий, мой вопрос: как я могу это решить? это rebol2 ok, чтобы обеспечить это «создание лица» или лучше попробовать что-то другое за пределами rebol2 (возможно, rebol3)?

Любая помощь будет принята с благодарностью.

ответ

1

Как уже отмечалось, проблема в том, что a повторно используется, не b!

Функция компоновки использует поле init для обработки таких вещей. Как я понимаю, init сначала привязан к грани, а затем вызван с do после того, как само лицо было создано (по крайней мере частично).

В этом случае я бы с помощью команды style в макете (по-прежнему частично с помощью объекта лица 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 
    ] 
] 

Другой альтернативы, немного более похожего на ваш будет:

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

Обратите внимание, что init вручную вызывается в предложении make в этом случае. Я не совсем уверен, зачем это нужно. Наконец, все могло элегантно быть решена в стиле

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

Второй подход работал лучше всего для моей проблемы, и это было просто/прозрачно для того, что я собирался построить дальше с этим кодом. Спасибо за сообщение: D – rdonatoiop

3

Rebol2 определенно подходит для этого.

Когда вы делаете это во второй раз, вы используете один и тот же экземпляр a. Это проблема.

Вы можете написать функцию, которая создает необходимые грани и добавляет их в блок и возвращает. Не забудьте создать '(первое лицо) каждый раз.

Кроме того, проверьте документацию на итерированные лица.

Здесь я добавил пример:

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

Вы можете изменить функцию, чтобы получить больше параметров, чтобы изменить цвет и другие аспекты, а также.

+0

Благодарим Вас за образец кода и для больших прозрений, особенно на повторных лицах. В настоящее время я изучаю те, которые, как я думаю (от того, что я читал до сих пор), мне немного лучше. Я намерен немного поиграть, а затем вернуть код, который я написал в ответном сообщении, ради совместного использования исследований. Еще раз спасибо: D – rdonatoiop

+1

Итерированные лица немного сложны в использовании, и об этом недостаточно. Но это полезно для элементов интерфейса таблицы/таблицы. – endo64

+0

извините, endo64; Изменил мой принятый ответ, хотя ваш ответ предоставил мне отличную информацию. – rdonatoiop

0

Я сказал в комментарии, что я вернусь, чтобы поделиться своими выводами, и я думаю, что у меня есть что-то интересное. Как отметил @ endo64, повторяющиеся лица сложны и, возможно, не подходят для того, что я намеревался сделать, когда я впервые задал вопрос - добиться простого/простого способа создания объектов через панели.

Я придумал нижеследующий код, который реализует своего рода instantiator. Это было частично вдохновлено основанием face-maker подхода @ endo64 наряду с некоторыми мастерами с итерированными лицами. Этот instantmator имеет ограничение ядра, которое не принимает несколько типов объектов, передаваемых в конструктор , который должен быть создан на той же панели.

В любом случае, я нашел, что это интересное мероприятие, и я хотел бы опубликовать его здесь, если он может быть кому-то полезен.


Я использую тот же код от вопроса, в настоящее время решения/обойти ограничение создания нескольких b объектов внутри главной панели макета. a и b теперь удерживают объект instantiator, который получает объект для создания внутри своей панели и блок позиций (пары смещений), где должны быть размещены объекты.

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 
] 

cоздателем экземпляров код:

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

Код для основного макета:

_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