VID布局面板支持多面创建[rebol2]
VID layout pane supporting multiple face creations [rebol2]
请考虑这个简单的 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 个 实例 of 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]
从消息中我推测 face b
以某种方式被重用并且弄乱了我想要实现的目标。我对此做了很多研究,在某些时候我发现可以通过克隆(使用 make
)要传递给 pane
的面部来绕过它;这就是我认为我正在做的,但根本没有成功。
鉴于这种情况,我的问题是:我该如何着手解决这个问题? rebol2 可以提供这个 "face-instantiation" 还是最好尝试 rebol2 之外的其他东西(也许是 rebol3)?
任何帮助将不胜感激。
Rebol2 绝对可以做到这一点。
当你第二次制作 b 时,你使用的是 a 的同一个实例。就是这个问题。
您可以编写一个函数来创建必要的面并将它们附加到一个块和 return。
不要忘记每次都创建一个(第一张脸)。
此外,检查文档中的迭代面孔。
这里我加了个例子:
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]
]
]
您可以更改函数以获得更多参数来更改颜色和其他方面。
我在评论中说过我会回来分享我的发现,我想我得到了一些有趣的东西。正如 @endo64 所指出的那样,迭代的面孔很棘手,可能不适合我第一次问这个问题时打算做的事情 - 实现 simple/straigthforward 通过面板实例化对象的方法。
我想出了下面的代码,它实现了一种实例化器。它的部分灵感来自 @endo64 的 face-maker 方法以及对迭代面孔的一些修补。此 instantiator 有一个核心限制,即不接受传递给要在同一窗格中创建的 constructor 的多种类型的对象。
无论如何,我发现这是一个有趣的练习,我想在这里 post 它以防它对某人有用。
我使用问题中的相同代码,现在 solving/circumventing 在主布局窗格中创建多个 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
正如已经指出的那样,问题是 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 子句中手动调用的。我不确定为什么需要它。
最后一切都可以用 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
]
请考虑这个简单的 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 个 实例 of 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]
从消息中我推测 face b
以某种方式被重用并且弄乱了我想要实现的目标。我对此做了很多研究,在某些时候我发现可以通过克隆(使用 make
)要传递给 pane
的面部来绕过它;这就是我认为我正在做的,但根本没有成功。
鉴于这种情况,我的问题是:我该如何着手解决这个问题? rebol2 可以提供这个 "face-instantiation" 还是最好尝试 rebol2 之外的其他东西(也许是 rebol3)?
任何帮助将不胜感激。
Rebol2 绝对可以做到这一点。
当你第二次制作 b 时,你使用的是 a 的同一个实例。就是这个问题。
您可以编写一个函数来创建必要的面并将它们附加到一个块和 return。 不要忘记每次都创建一个(第一张脸)。
此外,检查文档中的迭代面孔。
这里我加了个例子:
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]
]
]
您可以更改函数以获得更多参数来更改颜色和其他方面。
我在评论中说过我会回来分享我的发现,我想我得到了一些有趣的东西。正如 @endo64 所指出的那样,迭代的面孔很棘手,可能不适合我第一次问这个问题时打算做的事情 - 实现 simple/straigthforward 通过面板实例化对象的方法。
我想出了下面的代码,它实现了一种实例化器。它的部分灵感来自 @endo64 的 face-maker 方法以及对迭代面孔的一些修补。此 instantiator 有一个核心限制,即不接受传递给要在同一窗格中创建的 constructor 的多种类型的对象。
无论如何,我发现这是一个有趣的练习,我想在这里 post 它以防它对某人有用。
我使用问题中的相同代码,现在 solving/circumventing 在主布局窗格中创建多个 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
正如已经指出的那样,问题是 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 子句中手动调用的。我不确定为什么需要它。
最后一切都可以用 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
]