Closed Dassadar closed 8 years ago
This one does need a start{} - @a is not defined when alert is started. The Window do is not finished before alert runs.
There is a very important Shoes concept here that trips up everyone. If your Window do.. end was replaced with a button do..end then you see immediately that the @a is not defined because you didn't click the button. All Shoes GUI blocks {} or do..end will delay 'block' execution, even calls that you wouldn't think of like window because it can't proceed until the new window is on the screen, meanwhile alert has no block{} to wait on so it gets the current value of @a
Shoes.app do
@a = 'default'
window title:"test", width: 400, height: 120 do
@a = "2"
end
alert "/#{@a}/"
end
This actually a feature, not a bug and it bites every one who uses alerts in the Shoes.app block. It can take seconds or days before that light bulb goes bright.
Ok, still I don't get it in my real case which is a bit more context. In my window block, I am declaring a list_box (let's call it @a) with a list of choices. My windows does appear with the list_box, so @a is well defined and not nil.
Later on, I am refreshing the display (upon a click somewhere on the main window), and referring to @a to update the list of choices ==> @a is undefined, why ? :-/ And if not a bug, what is the correct way to refer to an object within a window block, outside this window block?
You want to set a widget's content or control it from one Shoes.app in another Shoes.app? (Window) Not as easy as you hoped for. https://github.com/Shoes3/shoes3/wiki/Poking-in-Shoes.app is an attempt to explain that mystery. @passenger94 , thinks I've made an error or two in that description but basically '@a' in Window1 may be different from '@a' in Window2. - you can get and compare object id's for both '@a' in each window - are they the same object? I suspect they are not.
Setting up an instance_eval from window 1 to an object in window 2 or vice versa requires clever meta programming and much head scratching. The Shoe manual and design explicitly states that each Shoes.app is independent . For example thats how the manual can run code snippets without crashing Shoes. For better or worse, that initial design decision is unlikely to change. Perhaps you can set up a observer/listener network to propagate changes between windows to maintain the illusion of a central MVC data store.
There is something else involved here besides the delay : at the time you invoke alert, @a is not yet defined and :
The window method is launching a new App and every App instance is like it's own closed world, whatever is defined inside the window block is unknown to the outside world. Even though the window method was called inside the app block !
There is the owner method on every App instance for those situation,
inside the window block (the "test" app) owner refers to the outside App, let's call it "main"
Shoes.app title: "main" do
@a = 'default'
button("check @a") {alert "/#{@a}/"}
window title:"test", width: 400, height: 120 do
@a = "2"
owner.set_a(@a)
end
def set_a(val)
@a = val
end
alert "/#{@a}/"
end
Ok thx for the explanations, that's clearer to me now. To implement an observer/listener mechanism however, I need to "talk" to the window block - how can I do that? If I am adding a method within the window block, can it be seen from outside? If so, how can I call it? Sorry for all these newbie questions ;-)
@a inside window is a totally different beast than the @a inside "main" you have to notify "main" by any means, observer for example, about the changes The alert you launch from the button knows about the changes, but not the first one.
Should it work the other way round? Something like:
Shoes.app title: "main" do
@a = 'default'
button("check @a") {alert "/#{@a}/"}
myWin = window title:"test", width: 400, height: 120 do
@a = 2
def setValue(val)
@a = val
end
end
myWin.setValue(3)
end
haha, would be cool ! but i'm afraid not without going into metaprogramming ... i didn’t try though At least we can say, not an easy, obvious way to do it like that !
This works !
Shoes.app title: "main" do
@a = 'default'
button("check @a") {alert "/#{@a}/"}
button("call my_met on test_app") {alert @test_app.my_met}
@test_app = window title:"test", width: 400, height: 120 do
@a = "2"
owner.set_a(@a)
def my_met
"my_met called"
end
end
def set_a(val)
@a = val
end
alert "/#{@a}/"
end
So the question is open :-)
My app will not work if all windows are not refreshed when a selection is done on one of them - else some unauthorized values in the list_box may be selected...
Hoping this metaprogramming for the master to talk to the child window can be done in a not-to-heavy way!
Le 2016-03-31 10:07, passenger94 a écrit :
haha, would be cool ! but i'm afraid not without going into metaprogramming ... i didn't try though At least we can say, not an easy, obvious way to do it like that !
You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub [1]
[1] https://github.com/Shoes3/shoes3/issues/233#issuecomment-203807742
My Ytm demo uses $vars for it's data store nstead of @vars for just this reason but that has strange side effects which is why it never moved past 'demo'. But I'm lazy and a bad programmer. However one $var which is a reference to a new Ruby class that holds the data for all views and has methods to add observers and notify them would not offend the ruby design gods, much. If that class also encapsulated your sql access (my assumption) then you could propagate changes to the db/class to the listeners.
Great passenger94, thanks!
Oh yes, using globals should work too !
I've just tested it on my apps (method within the window block called by outside block) --> just works perfectly! :-) ... and better than globals ;-)
Hello,
Here is my code:
I would like the alert to display /2/ and not //: what's wrong please?
Regards, David