Skip to main content

BeanShell + 2D = Instant Graphics

Posted by zixle on July 11, 2006 at 3:45 PM PDT

Over the years I've worked on a number of projects that involved
various 2D rendering operations. The usual cycle for such work is to
tweak rendering code, compile, run, examine the results using a
magnifier, and repeat until I'm happy with it. This certainly works,
but takes a bit longer than is ideal. When I needed to do a lot of
graphics tweaking for this years 'Extreme GUI Makeover' talk, I
figured it was time to see if I could streamline this process. This
blog shows what I've concocted.

I was looking for something that would allow me to get rid of the usual
compile and run cycle; I want instant feedback! More often than not I
need to zoom in on the results. As such, a magnifier would have to be
included. In the end I want Java code, so alternative scripting
languages aren't an option.

Thankfully I stumbled upon Bean
Shell
. BeanShell fit my needs perfectly! With BeanShell you can
evaluate blocks of Java code; just what I was looking for. Evaluating
raw Java code, for my purposes, is hardly interesting with out the
ability to supply state to the interpeter. BeanShell allows you to
supply state to the java code it executes. In this way I can pass a
graphics object to the interpeter that is available to the java code
that is executed. Putting all the pieces together enables me to
execute arbitrary Java code, rendering the results to an Image and
showing that Image using Swing components. Just what I wanted.

Here's the resulting application. For reasons I did not investigate
BeanShell won't run in the sandbox. As such, the application is signed
and needs to live outside the sandbox. Also note the application
stores the script in the file ~/.igeScript.



How does it work?

As you type in the text area a timer is started. When the timer fires
(~1 second) the script is evaluated in a background thread using
BeanShell. The intepreter is passed three variables: the width of the
image, the height of the image, and a graphics obtained from an image
of the specified size. If the interpeter successfully evaluates the
script, the image is rendered in two places. One shows the results at
actual size, the other scaled.

One of the first things you'll notice is the text area does no
completion for you. This is most definitely annoying! Ideally the
editor would behave just like that of NetBeans. As such, a better fit
would be to turn this into a NetBeans module. That way NetBeans would
provide all the completion, syntax highlighting, and error reporting
for free. Nice! If I have time, I'll do this; but don't hold your
breath;)

In my first take at the app I evaluated the script nearly immediately,
and on the EDT. This worked perfectly, until I typed in something
like:

  while (x < y) {
  }

As I was evaluating the script almost immediately, on the EDT, this
caused an infinite loop and I was screwed. This very rarely comes in
every day coding as you don't compile and run while typing. Not the
case here.

I was hoping BeanShell would allow me to stop the intepreter, but it
doesn't. To solve this problem I moved evaluating the script to a
separate thread. If the evaluation takes more than than 3 seconds, an
option pane is shown asking if the background thread should be
killed. To kill the background thread I use Thread.stop. This is
obviously bad, and can cause problems, but is better than causing the
app to be wedged...

Running the app

Try changing a couple of the variables at the top of the file to see
the results. For example, try changing TEXT_COLOR to
Color.RED and notice the effects render
immediately. Trying changing the KERNEL_SIZE and
BLUR_FACTOR to see the results on the drop shadow.

You can of course delete all the code and start a new.

Random other things

The app uses href="http://weblogs.java.net/blog/hansmuller">Hans's href="http://weblogs.java.net/blog/hansmuller/archive/2006/03/multisplitpane.html">MultiSplitPane
to house the components. This makes it easy to resize the app to fit
your needs.

I'm also using an early prototype of href="http://weblogs.java.net/blog/zixle/archive/2006/05/ease_of_swing_d.html">beans
binding to keep the model in sync with the width, height, scale
and text area. I'm still working on the legal issues of releasing this
code. I'll do a blog once it's all straightened out.

I'm using a variant of the application framework I had been developing
in my blog series on href="http://weblogs.java.net/blog/zixle/archive/2006/03/architecting_ap_2.html">architecting
applications. I will return to the application framework series,
but will stop development of the pieces that overlap with Hans's href="http://weblogs.java.net/blog/hansmuller/archive/2006/06/jsr_296_bows_sw.html">JSR
296: Swing appliction framework.

Full source can be found here.

    -Scott

Related Topics >>