Convert to and from BufferedImage in javafx 2.0

While porting Modellus from javafx1.3 using  javafx script to javafx2.0 using java language I ended up creating a class with a few helper methods for converting swing objects to and from javafx objects:

  • Converting from java.awt.color  to javafx.scene.paint.Color and vice versa
  • Converting from java.awt.image.BufferedImage to javafx.scene.image.Image and vice versa

Nothing too fancy but I thought it might come in handy to other people so here’s the code:

public class SwingUtils {

    public static java.awt.Color toAWTColor(javafx.scene.paint.Color fxColor)
    {
        return new java.awt.Color((float)fxColor.getRed(), (float)fxColor.getGreen(), (float)fxColor.getBlue(), (float)fxColor.getOpacity());
    }

    public static javafx.scene.paint.Color fromAWTColor(java.awt.Color awtColor)
    {
        return ColorBuilder.create()
                            .red(awtColor.getRed() / 255.0)
                            .green(awtColor.getGreen() / 255.0)
                            .blue(awtColor.getBlue() / 255.0).build();
    }

    // There is a problem with this implementation: transparent pixels on the BufferedImage aren't converted to transparent pixels on the fxImage.
    public static javafx.scene.image.Image convertToFxImage(java.awt.image.BufferedImage awtImage) {
    	if (Image.impl_isExternalFormatSupported(BufferedImage.class)) {
    		return javafx.scene.image.Image.impl_fromExternalImage(awtImage);
    	} else {
    		return null;
    	}
    }

    public static java.awt.image.BufferedImage convertToAwtImage(javafx.scene.image.Image fxImage) {
    	if (Image.impl_isExternalFormatSupported(BufferedImage.class)) {
    		java.awt.image.BufferedImage awtImage = new BufferedImage((int)fxImage.getWidth(), (int)fxImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
        	return (BufferedImage)fxImage.impl_toExternalImage(awtImage);
    	} else {
    		return null;
    	}
    }
}

This will probably be added on Lombard (next javafx version) as shown by this issue: http://javafx-jira.kenai.com/browse/RT-14038

Modellus 5 beta 1 release

(Update: the new Modellus site URL is http://modellus.pt)

Modellus 5 beta1 is available for download here. This version should be extremely usable.

Unpack files and run Modellus5.jar through the JVM (Java 1.6 update 20 is the minimum requirement). This is the PC version, I suspect some things won’t work on Mac and Linux although I haven’t tried it yet.

Modellus 5 is free. It is primarily used to aid teaching. By using only a mathematical language (no need to learn any new language) students and teachers are able to create models which then they can interact/view using animations/graphs/tables, etc.

From a technical standpoint, this version was created using javafx and swing. The animation window (background) was done in javafx while all the rest is Swing.

I’ll be posting more information about this version, shortly.

There are some examples you can try: here and here these are Modellus 4 examples though, they don’t use version 5 new features.

Let me know of any bugs you encounter or feature requests.

Event handling proposal

JavaFX brings a new event handling approach, making an improvement over the Java use of the too verbose observer pattern.

Normally in javafx you’ll use binding to listen to state changes and update other objects as appropriate. However this approach is not adequate when you want to listen to something that doesn’t imply a state change, something like say pressing a button (not a two state button, that would involve state).

With this post I wanted to share an idea I had about how javafx could handle those cases not covered by binding.

In JavaFX functions are variables, you can have a sequence of functions with this:

var buttonPressedListeners: function(:MouseEvent)[];

Let’s say you have a button and every time the button is pressed you iterate through the sequence above and call the listener functions. If you want to expose this to any interested listener you can declare the above sequence public. Now lets say a listener wants to register for listening, he can do so by inserting a function on the listener sequence:

insert fooListener into button.buttonPressedListeners;

If he wants to unregister this simple call would do it:

delete fooListener from button.buttonPressedListeners;

There is however a problem with this, you can insert the same listener two times into the sequence. We could iterate through the sequence list and check for duplicates but that would imply writing the same boiler plate code over and over again. So I would propose a language feature to enable declaring a sequence which doesn’t allow repeating values. Something like:

var buttonPressedListeners:  function(:MouseEvent) unique [];

Every time you want to call the functions on the sequence you’ll have to write down a for each statement which iterates through the sequence of functions, to fix this I would propose a second language feature: the ability to call all the functions in a function sequence with a single method call.

And that’s my event handling proposal. 🙂

Moving on…

Image by Mundilfari

On July 1st I’ll be no longer working full time with Modellus and as a consequence with JavaFX. I will however continue to work on it as an hobby, Modellus 5 is almost complete and I wish on having a very usable version on September.
From that point one, I preview Modellus will start to evolve at a quick pace taking advantage of the change of swing to javafx.

Despite some flawed features and omissions I’ve grown to like JavaFX very much, I think its based on solid concepts and will grow to become a very powerful language. I hope somewhere in the future I can continue working with it at a professional level..