2

I am using following code to add multiple GUI elements to a view via a foreach loop:

myRange: function [n][  ; to produce a vector of [1 2 3 4... n]
  vv: make vector! n 
  i: 1
  foreach j vv [
    vv/:i: i
    i: i + 1
    if i > n [break]]
  vv ]

view collect[ 
    foreach i myRange 10 [  
        print append "i in loop: " i
        keep [ t: text ]  keep append "message number: " i
        keep [field "entry"     button "Click" [t/text: "clicked"] return]
            ] ]

All GUI elements are being produced. But the code append "message number: " i is showing value of i to be 12345678910 in all text elements and not 1, 2, 3... 10 for different text elements.

Also, print append... statement is producing following output:

i in loop: 1
i in loop: 12
i in loop: 123
i in loop: 1234
i in loop: 12345
i in loop: 123456
i in loop: 1234567
i in loop: 12345678
i in loop: 123456789
i in loop: 12345678910

Moreover, clicking any button changes text of only the last added text element.

Where is the problem and how can it be solved? Thanks for your help.


Edit: It seems the language is converting my code from:

for i 1 10 1 [  
   print append "i in loop: " i  ]

to:

a_variable: "i in loop"
for i 1 10 1 [  
   print append a_variable i  ]

Which is not what I and (I think) most users want. In most languages a string "i in loop" will be taken as a constant and not converted to a variable since user has not specified it so. IMHO it will be easier for users of other languages to come here if such basic conventions are not altered.

4

3 回答 3

4

每当您看到这样的内容时,就意味着您未能创建新系列并重用现有系列。

为了解决这个问题,您需要创建一个新系列copy

例如。

print append copy "i in loop: " i

Rebol3/ren-c 不再有这个问题,因为源代码是不可变的,所以你会收到这样的代码的错误消息。

于 2017-09-17T05:59:17.380 回答
3

Rebol 和 Red 尽可能多地重用系列(例如字符串、块),如果您没有通过用 重新初始化等方式告诉它们。因此,如果您编写,您的问题应该会copy消失make

append copy "message number: " i
于 2017-09-17T05:57:58.383 回答
2

正如其他答案所暗示的那样,您的消息只使用一个字符串,并且需要复制。

至于另一个问题——你应该看看你正在生成的代码(正如我在其他地方建议的那样,你可以弹出一点PROBE来检查COLLECT函数的输出):

[
    t: text "message number: 1" field "entry" button "Click" [t/text: "clicked"] return 
    t: text "message number: 2" field "entry" button "Click" [t/text: "clicked"] return 
    t: text "message number: 3" field "entry" button "Click" [t/text: "clicked"] return 
    t: text "message number: 4" field "entry" button "Click" [t/text: "clicked"] return 
    t: text "message number: 5" field "entry" button "Click" [t/text: "clicked"] return 
    t: text "message number: 6" field "entry" button "Click" [t/text: "clicked"] return 
    t: text "message number: 7" field "entry" button "Click" [t/text: "clicked"] return 
    t: text "message number: 8" field "entry" button "Click" [t/text: "clicked"] return 
    t: text "message number: 9" field "entry" button "Click" [t/text: "clicked"] return 
    t: text "message number: 10" field "entry" button "Click" [t/text: "clicked"] return
]

正如你所看到的,你不断地重新分配t,所以最后它只指最后一张脸。

这里有几个选项——最突出的是生成您要为其分配text面孔的名称。在你的FOREACH循环中:

keep compose/deep [
    (to set-word! rejoin ["t-" i])
    text (rejoin ["Message Number: " i])
    field "entry"
    button "Click" [
        set in (to word! rejoin ["t-" i]) 'text "clicked"
    ]
    return
]

请注意,为了简化块创建,我使用了这一行:

set in (to word! rejoin ["t-" i]) 'text "clicked"

这包括(在第一个实例中):

set in t-1 'text "clicked"

IN'text返回绑定到给定上下文(人脸对象)的给定单词( ) t-1,然后是SETto "clicked"

更新

这个方法甚至不使用单词名称,只是使用一个共同的父级将按钮连接到标签:

view collect [
    keep [below space 0x0]
    foreach i myRange 10 [
        keep compose/deep [
            panel [
                origin 0x0
                text (rejoin ["Message Number: " i])
                field "entry"
                button "Click" [face/parent/pane/1/text: "clicked"]
            ]
        ]
    ]
]
于 2017-09-17T21:13:22.080 回答