图中没有显示正确的字符串事件

时间:2016-12-09 23:26:51

标签: rascal

在下面的代码中,我创建3个包含文本1到3的框,在第四个框中我想显示我的鼠标悬停在框上的文本。所以我为每个框设置了一个onMouseEnter FProperty,我更改了第四个框的字符串并告诉它重绘。

bool redraw = false;
str s = "0";
Figure getTextbox() {
    return computeFigure(bool() {bool temp = redraw; redraw = false; return temp; },
    Figure() {
        return text(str() {return s; });
    });
}

list[Figure] boxes = [];
for (i <- [1..4]) {
    boxes += box(text(toString(i)), onMouseEnter(void () {s = toString(i); redraw = true; }));
}

Figure changer = box(getTextbox());
render(vcat(boxes + changer));

但是,由于某些奇怪的原因,所有三个框都会告诉onMouseEnter方法将第四个框的文本更改为&#34; 3&#34; (最后一个框的值)而不是它们各自的值。

有什么线索的原因?谢谢!

1 个答案:

答案 0 :(得分:0)

啊,是的,这是for循环的变量捕获闭包问题,也可以从具有Javascript之类特殊功能的其他语言中获知。这是带有问题的代码:

i

变量onMouseEnter由void闭包绑定,而不是其值。因此,每次创建并传递给i的函数时,它都会读取3变量的最新值。由于在循环终止后调用回调,因此对鼠标输入函数的所有调用都将具有值for (i <- [1..4]) { newS = toString(i); boxes += box(text(toString(i)), onMouseEnter(void () {s = newS; redraw = true; })); }

为了解决这个问题并且做了你想做的事情,我相信下面的代码会起作用:

newS

这是有效的,因为对于for循环的每次传递都会创建一个绑定newS变量的新环境。因此,您将为每个循环获得一个新的i,而不是重用modified_at