【问题标题】:VID layout pane supporting multiple face creations [rebol2]支持多面创建的 VID 布局窗格 [rebol2]
【发布时间】:2015-04-29 03:01:12
【问题描述】:

请考虑这个简单的 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 的唯一 instance(让我这样称呼它)按应有的方式显示。

但现在假设我更改了代码,所以我有 b 的 2 个实例

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)?

任何帮助将不胜感激。

【问题讨论】:

    标签: rebol rebol2


    【解决方案1】:

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

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

    【讨论】:

    • 感谢您提供示例代码和出色的见解,特别是在迭代面孔上。我目前正在研究那些,我认为(从我目前阅读的内容来看)更适合我。为了研究共享,我打算玩一下,然后返回我在回复帖子中编写的任何代码。再次感谢:D
    • 迭代面有点难用,而且没有足够的文档说明。但它对于网格/表格样式的 UI 元素很有用。
    • 对不起,endo64;更改了我接受的答案,尽管您的回答为我提供了深刻的见解。
    【解决方案2】:

    正如已经指出的那样,问题是 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
    ]
    

    【讨论】:

    • 第二种方法最适合我的问题,并且对于我接下来打算使用此代码构建的内容而言,它是直接/透明的。感谢您发帖:D
    【解决方案3】:

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

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

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


    我使用问题中的相同代码,现在解决/规避在主布局窗格内创建多个 b 对象的限制。 ab 现在拥有一个 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-12
      • 2017-02-10
      • 2023-03-10
      • 2011-07-22
      • 1970-01-01
      • 2013-10-27
      相关资源
      最近更新 更多