From: Noel Rappin Date: 2001-02-13T00:19:13+09:00 Subject: [ruby-talk:10727] Re: Ruby/Tk, what am I doing wrong... [long answer] Jeremy, thank you very much for this -- it's a very clear and lucid explanation of what's going on. I only hope that I can do as good a job passing the knowledge down to the next batch of newbies!. Noel > Noel Rappin wrote: > >Now I'm diving into Ruby/Tk and I have some newbie type questions... > > Welcome! I hope you're not offended that a fellow newbie answers your > questions since I have myself come across most of these very things myself > in the past three weeks! =) > > > >Question 1: I'm creating a root window and then a subordinate TkToplevel. > >The TkTopLevel is always drawn behind the root... I want it to > start out in > >front (changing the order of the display calls doesn't seem to > matter). How > >can I change the Z-order of the windows? > > I found using the "lower" method to the TkRoot window works well: > > rw = TkRoot.new > mw = TkToplevel.new(rw) > mw.lower > Tk.mainloop > > > > >Question 2: I'm seeing inconsistencies between different kinds of widget > >invocation. For example: > > > >@variable = TkVariable.new > >TkEntry.new(entryFrame, 'textvariable' => @variable) > > > >works, however... > > > >@variable = TkVariable.new > >TkEntry.new(entryFrame) { > > textvariable variable > >} > > > >returns the following error: > > > >/cygdrive/c/ruby/lib/ruby/1.6/tk.rb:2239:in `tk_trace_variable': requires > >TkVariable given NilClass (ArgumentError) > > from /cygdrive/c/ruby/lib/ruby/1.6/tk.rb:2636:in `textvariable' > > This is because you didn't use the same variable: > In the first instance: > > >@variable = TkVariable.new > >TkEntry.new(entryFrame, 'textvariable' => @variable) > > You are referencing @variable correctly; however in the second instance: > > >@variable = TkVariable.new > >TkEntry.new(entryFrame) { > > textvariable variable > >} > > You are (implicitly) referencing 'variable' which is not the same as > @variable, unfortunately! Because 'variable' [a local variable] has not > been assigned a value, it's value is implicitly 'nil', thus causing the > error you saw. Now I know what you're thinking -- you've already tried > doing this: > > >@variable = TkVariable.new > >TkEntry.new(entryFrame) { > > textvariable @variable > >} > > And you got this error: > > /usr/local/lib/ruby/1.6/tk.rb:2239:in `tk_trace_variable': > requires TkVariable given NilClass (ArgumentError) > > But that is becuase inside of the {} body of your TkEntry initialization, > the scope of method variables is for the TkEntry and _not_ for > your enclosing > class! That is why in the fully-parenthesized version it works: > > >TkEntry.new(entryFrame, 'textvariable' => @variable) > > but in the block-version it doesn't: > > >TkEntry.new(entryFrame) { > > textvariable @variable > >} > > Fortunately, in my case, the problem was that I was not familiar with how > in ruby, all variables are references to an object, and not actually the > object itself. It took me several hours before I got it into my head that > all variables are just references and that it doesn't matter what > the variable > name *is*, only that it *is* in scope! =) This is a somewhat > different way > of approaching OOP than in, say, C++. All you have to do here is > create a > local variable -- which will be in scope! > > @variable = TkVariable.new > localvar = @variable > TkEntry.new(entryFrame) { > textvariable localvar > } > > and, Viola! > > > > >Similarly... > > > >TkEntry.new(@window) { > > pack('side' => 'left') > >} > >TkButton.new(@window) { > > pack('side' => 'left') > >} > > > >correctly puts the two side by side left to right, however > > > >TkEntry.new(@window) { > > pack {side 'left'} > >} > >TkButton.new(@window) { > > pack {side 'left} > >} > > > >puts the two items top to bottom. > > This is because you can't nest the "block" notation with the > "pack" method. > I don't have an explanation for why this doesn't work, but as far as I can > tell, it does not work. I've just resigned myself to using the > parenthesized > form. What is happening is that the 'pack' method is being passed no > arguments at all, and so the default behavior (top to bottom packing) is > occuring. > > > >The pickaxe book implies that in both cases the two forms should be > >equivalent. What am I doing wrong? > > Maybe someone will shed light on this last question and englighten both > of us. =) > > Jeremy >