From: Ron Jeffries Date: 2001-03-21T08:10:02+09:00 Subject: [ruby-talk:12989] Re: TextBox ListBox (Access to @vars) OK, here's what's confusing us now. we have code like what's included at the end here. (sorry it's so big, I'm not sure what to clip to leave it still working): Basically we are building a hashview object that when created, creates a window upon initialize. The window has a listbox and a textbox as before. When you click a key, the value displays. You can define a new value or redifine an old one by typing the association in the text window and typing Control-s. For example x => this is a new value for x So our object wants to have the hash (we call it a dictionary because we are old-fashioned) as an instance variable. (We'll be opening the view on a TopLevel or something in the future, so there can be more than one.) Now when you add an item, we have to refresh the list box from the keys of the dictionary. We have set up a general bind of Control-s, so that code needs access to the listbox. We originally had the listbox as a local variable in the setup of the frame (copying from one of the demos), and learned that we had to define the local (keyListbox) as nil OUTSIDE the proc, to get access to it later on, in the code that inserts hash keys into the list box. We wanted to implement the refreshList method on HashBrowserView, so we wanted to change the local keyListbox to an instance variable. The obvious change, replacing keyListbox with @keyListbox, doesn't work. We are guessing that the @variables inside the proc are defining themselves into the proc. So the only way we could think of to get the variable set was to write a setter for the instance variable and send it: defineWidget(keyListbox) As I think about it now, we could probably put an explicit scope on the variable, ala HashBrowserView::@keyListbox and just use that everywhere. I'll try that if I can figure out the syntax ... Are we on the right track here? Is it true that @variable inside a proc defines an instance variable on the proc instance? Is there a better, cleaner way to do what we're trying to do? Thanks! Ron ================================== require 'tk' require 'tkencoding' require 'tkafter' class HashBrowserView def initialize(aDictionary) @dictionary = aDictionary @methodListWidget = nil hashBrowserView = TkRoot.new {|w| title("Dictionary Browser") #positionWindow(w) } hashBrowserView.bind("Control-s", proc {save}) keyListbox = nil TkFrame.new(hashBrowserView, 'borderwidth'=>10) {|w| s = TkScrollbar.new(w) keyListbox = TkListbox.new(w) { setgrid 1 width 10 height 12 selectmode 'single' yscrollcommand proc{|first,last| s.set first,last} } s.command(proc{|*args| keyListbox.yview *args}) s.pack('side'=>'right', 'fill'=>'y') keyListbox.pack('side'=>'left', 'expand'=>1, 'fill'=>'both') }.pack('side'=>'top', 'expand'=>'yes', 'fill'=>'y') @dictionary.keys.each { |key| keyListbox.insert('end', key) } @textBox = TkText.new(hashBrowserView, 'height'=>10) @textBox.pack keyListbox.bind('ButtonRelease-1', proc{ sel = keyListbox.curselection selection = keyListbox.get(sel) @textBox.delete('1.0','end') @textBox.insert('1.0', @dictionary[selection])}) defineWidget(keyListbox) end def defineWidget(aWidget) @methodListWidget = aWidget end def save value = @textBox.get('1.0','end') value =~ /([\w+]) +=> +(.+)/ @dictionary[$1] = $2 refreshList end def refreshList @dictionary.keys.each { |key| @methodListWidget.insert('end', key) } end end dictionary = {'a'=>'this is the text for a', 'b'=>'and here is good old b' } hashBrowser = HashBrowserView.new(dictionary) Tk.mainloop Ronald E Jeffries http://www.XProgramming.com http://www.objectmentor.com