5

请考虑这个简单的 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 是否可以提供这种“面部实例化”,或者最好在 rebol2 之外尝试其他东西(也许是 rebol3)?

任何帮助将不胜感激。

4

3 回答 3

3

Rebol2 绝对可以做到这一点。

当您第二次 MAKE b 时,您正在使用 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]
    ]
]

您可以更改函数以获取更多参数以更改颜色和其他方面。

于 2015-04-29T20:59:20.187 回答
1

正如已经指出的那样,问题是a被重用,而不是b

布局函数使用一个字段init来处理这样的事情。据我了解,它init首先绑定到面部,然后do在面部本身实例化(至少部分)之后调用。

在这种情况下,我将style在布局中使用命令(仍然部分使用 face object 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
]
于 2015-06-14T05:10:21.733 回答
0

我在评论中说过我会回来分享我的发现,我想我得到了一些有趣的东西。正如@endo64 所指出的那样,迭代面很棘手,也许不适合我第一次问这个问题时的意图——通过面板实现一种简单/直接的方式来实例化对象。

我想出了下面的代码,它实现了一种实例化器。它的部分灵感来自@endo64的面部制作方法以及对迭代面部的一些修补。实例化器有一个核心限制,即不接受传递给构造函数以在同一窗格中创建的多种类型的对象。

无论如何,我发现这是一个有趣的练习,我想把它贴在这里,以防它对某人有用。


我使用问题中的相同代码,现在解决/规避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
]

实例化代码是:

_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
于 2015-05-03T22:22:11.337 回答