[fxruby-users] Attribute Binding

Joel VanderWerf vjoel at PATH.Berkeley.EDU
Sat Feb 12 16:36:18 EST 2005

Berin Loritsch wrote:
> I am generally new to Ruby and more specifically FXRuby.  I come from a 
> Java background, but have been recently looking at SmallTalk and Ruby 
> and I wanted to compare and contrast the languages.  I have a library in 
> Java that will allow me to bind a class attribute directly to a GUI 
> control.  It uses JavaBean technology and the PropertyChangeEvent 
> signals that are sent every time the value changes.  SmallTalk provides 
> this support as part of the core language.  My question is how do I do 
> that with Ruby?
> For example, I have a BankAccount class (yes I know its a toy app, but 
> it will help me understand what to do) with a "balance" attribute.  The 
> BankAccount class works wonderfully by itself.  I have a method to 
> deposit and a method to withdraw funds from this BankAccount class.  I 
> want to be able to set up a button like this:
> FXButton.new(window, "&Deposit").connect(SEL_COMMAND) { @account.deposit 
> 200 }
> And as a result of that action have the FXTextField automatically update 
> itself with the new balance.  I don't see a lot of examples of this type 
> of thing, and I am not even sure if it is possible (it must be).  Has 
> anyone had any luck with this?


There are two ways I know of doing this. Fox itself provides one way, 
FXDataTargets. There is an example in the FXRuby distribution.

Another way is to use two libraries I have developed: FoxTails and 
Observable, available at http://raa.ruby-lang.org. Briefly, Observable 
lets you designate an attribute as "observable", in which case various 
parts of your app can register to be informed when the value changes. 
FoxTails uses this to wire up widgets like text fields, sliders, scroll 
bars, etc. (There are some other things in FoxTails, too.)

Your example might look something like this:

require 'foxtails'

include Fox
include FoxTails

class Account
   extend Observable

   observable :balance
   def deposit amt
     self.balance += amt
       # Don't use @balance, or observers not notified.

class AccountWindow < FXMainWindow
   def initialize(*args)

     @account = Account.new
     @account.balance = 0

     FXButton.new(self, "&Deposit").connect(SEL_COMMAND) {
       @account.deposit 200

     int_field = FTIntegerField.new(self, 10, @account, :balance, 

   def create

class AccountApp < FTApp
   def initialize
     super("Account", "TEST")
     AccountWindow.new(self, "Account")


You can also register for notification from non-gui code, using "when_" 

   some_account.when_balance CHANGES do |new_bal, old_bal|

The CHANGES thingy is just something that matches the new value, using 
ruby's === matching. CHANGES is actually the class Object, which matches 
everything. (Because === is =~ for strings, you can use regexes to match 
strings. Also, you can extend it as you wish by defining === in your 
classes.) This is documented in the observable project.

FoxTails is currently for Fox 1.0, but I have a "shim" file you can 
include to get most of it to work with 1.2. I apologize in advance for 
the state of the documentation, but at least there are examples, and the 
FT*Field classes have almost the same api as the FX*Field classes.

Btw, the current version of FoxTails has a nice way of generating text 
fields, check/radio buttons, option menus, and static text using a 
syntax much like good ol' printf. The fields are automatically wired up 
to the observable attrs that you specify. See examples/fields.rb.

More information about the fxruby-users mailing list