MVC and Window.closeAll

Hi all,

I’m taking some time to understand the MVC (model-view-controller) paradigm more deeply. I’m noticing some odd behavior when a block of GUI code begins with Window.closeAll. One the first evaluation, the following code works fine AFAICT. However, if re-evaluated as-is, the MVC relationships disappear — the sliders and number box no longer move together. But, if I manually close the window first, or run Window.closeAll (or ~win.close) as a separate statement before re-evaluating the code chunk, things work fine.

I would guess this is related to the precise order in which the interpreter deals with these tasks (removing the old dependent, closing the window, creating a new window, creating a new dependent), but I’m pretty clueless. Is this a bug, or am I doing something wrong?


~model = [0.75];
~ctrl =;
~ctrl.put(\val, {{ |v| v.value_(~model[0]) }) });

~win =,100,100,325))
~win.onClose_({ ~ctrl.remove });

~view = [
	Slider(~win, Rect(25,25,25,250))
	.action_({ |v| ~model.put(0, v.value).changed(\val) }),

	Slider(~win, Rect(50,25,25,250))
	.action_({ |v| ~model.put(0, v.value).changed(\val) }),

	NumberBox(~win, Rect(25,275,50,25)).align_(\center)
	.action_({ |v| ~model.put(0, v.value).changed(\val) })

Here’s a case where global variables are risky. You have no guarantee that ~win.onClose_({ ~ctrl.remove }); is operating on the same controller that was created for that specific window.

I’d use local (declared) variables for these. You can retain extra references in environment variables for debugging if you need to, but the MVC stuff should be local.

EDIT: I think it’s that the onClose function must wait until the entire block has finished – SC threads are non-preemptive, so this function can’t interrupt the function (your code block) that’s already executing. So ~ctrl has already changed to the new one, before the window close function removes it. You might be assuming that closing windows is synchronous but it seems that not all of it is. EDIT EDIT scztt beat me to this by a minute.

Local variables will solve that problem.


Exactly right. The onClose callback is called asynchronously some time in the future after closeAll - at that point, you have pointed ~ctrl to your NEW SimpleController, so you’re effectively removeing immediately after you create and connect.

Interesting — makes sense. Thanks both.