2016-12-09 7 views
2

В следующем коде я создаю 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 изменить текст четвертого ящика в «3» (значение последнего ящика) вместо их индивидуальной стоимости.

Любая подсказка почему? Благодаря!

ответ

0

Ах, да, это проблема с захватом переменной, которая связана с циклами, также известными на других языках, которые имеют эту особенность, такую ​​как Javascript. Это код с вопросом:

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

Переменная i связана с закрытием пустот, а не его значение. Поэтому каждый раз, когда функция, созданная и переданная в onMouseEnter, будет считываться последнее значение переменной i. Поскольку callback вызывается после завершения цикла, все вызовы функции ввода мыши будут иметь значение 3.

Чтобы это исправить, и «делать то, что вы хотите», следующий код будет работать, я считаю,:

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

Это работает, потому что для каждого прохода для цикла создается новая среда, которая связывает переменную newS , Таким образом, вы получите свежий newS для каждого цикла вместо повторно используемого i.