2016-12-09 20 views
2

次のコードでは、1〜3のテキストで3つのボックスを作成し、4番目のボックスでマウスの上にマウスを置いたボックスのテキストを表示します。だから、私は4つ目のボックスの文字列を変更し、それを再描画するように指示する各ボックスに対して、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)); 

しかし、いくつかの奇妙な理由で、すべての3つのボックスではなく、個々の値の「3」(最後のボックスの値)に第四ボックスのテキストを変更するonMouseEnter方法を教えてくれます。

何か手掛かりがありますか?ありがとう!

答えて

0

ああ、これはforループの可変キャプチャクロージャの問題です。これはJavascriptのような特定の機能を持つ他の言語でも知られています。これが問題とコードです:

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

変数iは、ボイドの閉鎖ではなく、その値に拘束されています。したがって、作成された関数がonMouseEnterに渡されるたびに、i変数の最新の値が読み込まれます。ループが終了した後にコールバックが呼び出されるため、マウス入力関数へのすべての呼び出しの値は3になります。

は、次のコードは、私は信じて働くだろう「あなたがやりたい」これを修正し、するには、次の

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

これが機能するためにnewS変数をバインドし、新しい環境が作成されたforループのすべてのパスの。したがって、再利用されたiではなく、すべてのループに対して新鮮なnewSが得られます。

関連する問題