Noel Rappin <noel.rappin / openwave.com> 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