Home | Back | Contents | Next |
buttonHandler = new ActionListener() { actionPerformed( event ) { print(event); } }; button = new JButton(); button.addActionListener( buttonHandler ); frame(button); |
ActionListener
interface and assigned it to a variable called
buttonHandler.
The buttonHandler object contains the scripted method actionPerformed(),
which will be called to handle invocations of that method on the interface.
Note that in the example we registered our scripted ActionListener with a
JButton using its addActionListener() method. The JButton is, of course,
a standard Swing component written in Java. It has no knowledge that when it
invokes the buttonHandler's actionPerformed() method it will actually be
causing the BeanShell interpreter to run a script to evaluate the outcome.
To generalize beyond this example a bit - Scripted interfaces work by looking
for scripted methods to implement the methods of the interface.
A Java method invocation on a script that implements an interface causes
BeanShell to look for a corresponding scripted method with
a matching signature (name and argument types). BeanShell then invokes the
method, passing along the arguments and passing back any return value.
When BeanShell runs in the same Java VM as the rest of the code, you can
freely pass "live" Java objects as arguments and return values, working
with them dynamically in your scripts; the integration can be seamless.
See also the dragText example.
actionPerformed( event ) { print( event ); } button = new JButton("Foo!"); button.addActionListener( this ); frame( button ); |
ActionEvents
are fired by the button, your
actionPerformed() method will be invoked. The BeanShell 'this' reference
to our script implements the interface and directs method invocations to the
appropriately named method, if it exists.
Note: If you want to have some fun, try entering the previous example interactively in a shell or on the command line. You'll see that you can then redefine actionPerformed() as often as you like by simply entering the method again. Each button press will find the current version in your shell. In a sense, you are working inside a dynamic Java object that you are creating and modifying as you type. Neat, huh? Be the Bean! |
messageButton( message ) { JButton button = new JButton("Press Me"); button.addActionListener( this ); JFrame frame = frame( button ); actionPerformed( e ) { print( message ); frame.setVisible(false); } } messageButton("Hey you!"); messageButton("Another message..."); |
actionPerformed( event ) { print( event ); } button.addActionListener( (ActionListener)this ); // added cast |
mouseHandler = new MouseListener() { mousePressed( event ) { print("mouse button pressed"); } invoke( method, args ) { print("Undefined method of MouseListener interface invoked:" + name +", with args: "+args ); } }; |
import javax.xml.parsers.*; import org.xml.sax.InputSource; factory = SAXParserFactory.newInstance(); saxParser = factory.newSAXParser(); parser = saxParser.getXMLReader(); parser.setContentHandler( this ); invoke( name, args ) { print( name ); } parser.parse( new InputSource(bsh.args[0]) ); |
Tip: You can use the invoke( name, args ) meta-method directly in your own scope or in the global scope as well, in which case you can handle arbitrary "unknown" method invocations yourself, perhaps to implement your own "virtual" commands. Try typing this on the command line: invoke(name,args) { print("Command: "+name+" invoked!"); } noSuchMethod(); // prints "Command: noSuchMethod() invoked!" |
foo() { run() { // do work... } return this; } foo = foo(); // Start two threads on foo.run() new Thread( foo ).start(); new Thread( foo ).start(); |
Note: You can use the bg() "background" command to run an external script in a separate thread. See bg(). |
Home | Back | Contents | Next |