[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?
Berin,
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.
end
end
class AccountWindow < FXMainWindow
def initialize(*args)
super
@account = Account.new
@account.balance = 0
FXButton.new(self, "&Deposit").connect(SEL_COMMAND) {
@account.deposit 200
}
int_field = FTIntegerField.new(self, 10, @account, :balance,
FRAME_SUNKEN)
end
def create
super
show
end
end
class AccountApp < FTApp
def initialize
super("Account", "TEST")
FoxTails.get_standard_icons
AccountWindow.new(self, "Account")
end
end
AccountApp.new.run
---------------------------------
You can also register for notification from non-gui code, using "when_"
clauses:
some_account.when_balance CHANGES do |new_bal, old_bal|
...
end
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