图没有显示正确的事件字符串
Figure doesn't show correct string on event
在下面的代码中,我用文本 1 到 3 创建了 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 方法将第四个框的文本更改为“3”(最后一个框的值)而不是它们各自的值。
知道为什么吗?谢谢!
啊,是的,这是 for 循环的变量捕获闭包问题,也从具有此特定功能的其他语言中知道,例如 Javascript。这是有问题的代码:
for (i <- [1..4]) {
boxes += box(text(toString(i)), onMouseEnter(void () {s = toString(i); redraw = true; }));
}
变量 i
被 void 闭包绑定,而不是它的值。所以每次创建并传递给 onMouseEnter
的函数都会读取 i
变量的最新值。由于回调是在循环终止后调用的,因此所有对鼠标输入函数的调用都将具有值 3
。
要解决这个问题 "do what you want",我相信以下代码可以工作:
for (i <- [1..4]) {
newS = toString(i);
boxes += box(text(toString(i)), onMouseEnter(void () {s = newS; redraw = true; }));
}
这是可行的,因为 for 循环的每一次传递都会创建一个绑定 newS
变量的新环境。所以你会为每个循环得到一个新的 newS
而不是重复使用的 i
。
在下面的代码中,我用文本 1 到 3 创建了 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 方法将第四个框的文本更改为“3”(最后一个框的值)而不是它们各自的值。
知道为什么吗?谢谢!
啊,是的,这是 for 循环的变量捕获闭包问题,也从具有此特定功能的其他语言中知道,例如 Javascript。这是有问题的代码:
for (i <- [1..4]) {
boxes += box(text(toString(i)), onMouseEnter(void () {s = toString(i); redraw = true; }));
}
变量 i
被 void 闭包绑定,而不是它的值。所以每次创建并传递给 onMouseEnter
的函数都会读取 i
变量的最新值。由于回调是在循环终止后调用的,因此所有对鼠标输入函数的调用都将具有值 3
。
要解决这个问题 "do what you want",我相信以下代码可以工作:
for (i <- [1..4]) {
newS = toString(i);
boxes += box(text(toString(i)), onMouseEnter(void () {s = newS; redraw = true; }));
}
这是可行的,因为 for 循环的每一次传递都会创建一个绑定 newS
变量的新环境。所以你会为每个循环得到一个新的 newS
而不是重复使用的 i
。