http://www.developer.com/

Back to article

Using NetBeans to Develop a JavaFX Desktop Application


July 1, 2009

In the spring of 2007, Sun released a new framework named JavaFX. The main component of JavaFX is JavaFX Script, which is a declarative scripting language that mixes the best capabilities of the Java platform with classes designed for implementing media functionalities in an easier manner. Now, you can develop GUIs, animations, audio/video players, and cool effects for text and graphics, as well as access web services for the desktop, browser, and mobile platforms with only a few straightforward lines of code. In addition, you can wrap Java and HTML code into JavaFX Script.

In December 2008, Sun unveiled the release of JavaFX 1.0, a new platform that merges form and functionality for building rich Internet applications (RIA) with immersive media and content for web browsers and desktops. Looking forward, the newer NetBeans release contains support for JavaFX 1.0 under the NetBeans IDE 6.5 for JavaFX 1.0 name.

This article explains how to use this NetBeans release to develop a JavaFX Script desktop application.

Download and Install NetBeans 6.5 for JavaFX 1.0

This section presents the prerequisites for following the remainder of the article. You should be in one of the following scenarios:
  • You have a previous NetBeans version and you want the JavaFX plug-in. Use this guide to get the plug-in.
  • You want to download NetBeans 6.5 and JavaFX 1.0 as a bundle. Download it from the NetBeans site and just follow the setup instructions.

For system requirements, check the JavaFX spec page.

A Brief Presentation of the Application

In the following sections, you'll develop five JavaFX classes (*.fx) that will develop a desktop application named DeltaCars. Basically, the application will mimic a commercial for a company that rents cars. The potential clients can see a video presentation of the company, available cars, prices, contacts, and so on. In principle, four of the five classes will represent individual graphical components and the last class will represent the main class of the application (see Figure 1). This main class will be the application stage. Every class will wrap the graphical capabilities of the represented component, such as transparency, events listeners, translations, interactions, effects, audio/video components, etc.



Click here for larger image

Figure 1: Splitting the Application into JavaFX Classes

Create a JavaFX Project Stub

Because NetBeans comes with a JavaFX engine and JavaFX support, creating a JavaFX project stub is a very simple task. Start by launching NetBeans 6.5 and then following with these steps:
  1. From the main File menu, select the New Project option (this will open the New Project wizard).
  2. In the Choose Project, Categories section, select JavaFX from the available categories. This will activate a list of JavaFX project types in the Projects section.
  3. You will see only one type of JavaFX project, JavaFX Script Application. Select it from the Projects section and press the Next button. You should see the wizard page for the project settings.
  4. In the project settings page, enter the project name and location in the Project Name and Project Location fields. For this example, your project name is DeltaCars and its location is the C:\JavaApplications\JavaFX folder.
  5. Because you don't have/need a previous project or set of classes, select the Empty Project radio button for the DeltaCars project. If you selected the From Sources radio button, you would be prompted to provide the source package folders.
  6. Allow NetBeans to select DeltaCars as the main project and to generate the corresponding main class.
  7. Press the Finish button.

After you press the Finish button, NetBeans will generate the DeltaCars project stub. You should see its tree structure in the Projects view, the Main.fx class in the NetBeans main editor, and the JavaFX Palette (see Figure 2).



Click here for larger image

Figure 2: The DeltaCars Stub in NetBeans 6.5

If the JavaFX Palette is not visible by default, then you can activate it by selecting the Palette option from the Window main menu.

Develop the Main Class of the Application

The main class of your application is named Main.fx, and it is available in the Projects view, under the DeltaCars -> Source Packages -> deltacars node. As you can see, NetBeans already has populated it with the main imports and it has defined a default Stage and a Scene for your application. These JavaFX classes, much like CustomNode, Group, and Node, represent the main instruments of the JavaFX language. Here is a brief overview of the classes:
  • Stage: This class represents the top-level container for the JavaFX application.
  • Scene: This class represents a canvas on which JavaFX renders graphical content. It usually contains Nodes that represent graphical components. The Scene is contained by Stage.
  • CustomNode: This class represents a subclass of Node. It is created by overriding the create function. It can have one child node.
  • Group: This class represents a set of child nodes.
  • Node: This class represents a graphical component on a scene.

Now, if you examine the Main.fx generated code, you will notice that by default NetBeans uses a Stage of 250x80 pixels, titled "Application title" and a Scene that contains a single Node of type Text. To modify these settings for your application, follow these steps:

  1. Rename the Stage title by replacing "Application title" with "Delta Cars."
  2. Resize the Stage replacing the 250x80 pixels with 712x442 pixels.
  3. Because you need a window that is not resizable, add the resizable: false attribute.
  4. Delete all the content on the Scene, leaving only the corresponding accolades.
  5. Set the Scene background color to black: Add the Scene's fill attribute, expand the Colors Palette, drag the Black item from the palette, and drop it where the fill's value should be written (you can use the Colors Palette wherever you need to set a color property). Notice that a Color is an instance of the javafx.scene.paint.Color class.
  6. Your Scene is now empty. So the content attribute should look like content: [].

At this point, the code of Main.fx should look like this:

package deltacars;
 
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.paint.Color;
 
Stage {
    title: "Delta Cars"
    width: 712
    height: 442
    resizable: false
    
    scene: Scene {
        fill:Color.BLACK
        content: []
    }
}

If you run the project, you should see an empty black window titled "Delta Cars."

Author's Note: If you ever want to add a Stage or a Scene from scratch, you can expand the Applications Palette and drag-and-drop the corresponding item in the JavaFX class editor. This will provide a basic implementation populated with the minimum requirements.

Creating the DeltaTitleRect.fx Class

Starting with this section, you will develop the application's graphical components. Every node that represents a graphical component is a JavaFX file, and at this point you know how to create such a file. Per the previous example for creating the DeltaTitleRect.fx file, follow these steps (use this approach to create all the files of the DeltaCars application):
  1. In the Projects view, expand DeltaCars -> Source Packages and select the deltacars node.
  2. Right-click on the deltacars node and select the New -> Empty JavaFX File option (from the same contextual menu, you can choose to create a new JavaFX Class or a JavaFX Stage).
  3. In the New Empty JavaFX File wizard, type DeltaTitleRect as the file name (don't type the .fx extension).
  4. Press the Finish button.

Now the DeltaTitleRect.fx file is located under the deltacars node. Open DeltaTitleRect.fx in the editor, where you will transform it into a JavaFX Node. Because a graphical component is just an element in a scene graph, it has to extend the CustomNode class. You accomplish this task from the Applications Palette by dragging a CustomNode item on the editor surface under the comment "place your code here." You should see something like Figure 3.



Click here for larger image

Figure 3: Creating a JavaFX Node

Next, replace the MyCustomNode class name with your name, DeltaTitleRect, and place the public keyword in front of the class (the public keyword is necessary to increase the class visibility).

Author's Note: All the JavaFX classes developed in the section to follow should extend the CustomNode class and should be declared public.

The next step is implementing the graphical design of the DeltaTitleRect.fx class. This class should map some text (Text node) and two colored rectangles (Rectangle node). As you can see in Figure 4—if you use a little imagination—before the Text is set in its final place, it is transformed with the scale and translate transformations.



Click here for larger image

Figure 4: Scale and Translate a Text Node

To accomplish these transformations, you will use a keyframe animation. This kind of animation controls changes in properties such as scale, translate factor, or opacity over time by defining the property's values at key times and interpolating the values in between. To define a keyframe animation, you need to define the following objects:

  • Timeline: This object represents a list of key frames that are controlled through a start function (play) and a stop function (stop). In addition, the animation can be repeated using the repeatCount attribute.
  • KeyFrame: This object represents a set of end states of various object values at a certain time instant relative to the start of the animation. It uses these values along with interpolation specifications to calculate the in-between values relative to the previous frame.
  • KeyValue: This object represents a target, which is a reference to an object to animate, a value for the object to take on at the KeyFrame time, and an Interpolator. The supported interpolations types are:
    • Interpolator.LINEAR (The default): Uses simple linear interpolation.
    • Interpolator.EASEOUT: Starts changing the value slowly after the KeyFrame.
    • Interpolator.EASIN: Slows the rate of change as the KeyFrame is reached.
    • Interpolator.EASEBOTH: Smoothes the rate of change through the KeyFrame.

Now, that you know what a keyframe animation is, follow these steps to implement one in DeltaTitleRect.fx:

  1. Expand the Animation Palette.
  2. Drag a Timeline item right below the create function definition.
  3. Drag a Values item right below the canSkip attribute of the Timeline.
  4. Modify the generated code (the left side of Figure 5 ) to conform to the right side of Figure 5.



    Click here for larger image

    Figure 5: Modifying a Generated Timeline

Now that you have a keyframe animation, it is time to define the graphical components for the DeltaTitleRect.fx class. Both types of components can be added from the Basic Shapes Palette by dragging two Rectangle items and two Text items inside the Group content. After dropping them inside the default Group, you should adjust them to conform to the code in Listing 1 (to add Scale and Translate nodes, use the Transformations Palette).

Creating the DeltaCarLogo.fx Class

Like any serious company, Delta Automotive needs a logo. Their logo features a car image named logoCar.bmp, which is stored in the deltacars/img folder (you can find this image in the source code download for this article). The image will be displayed in the upper-left corner of the Scene through a fade transition. The javafx.animation.transition package contains JavaFX’s transition functionality, which includes path, parallel, rotate, scale, fade, and other transitions.

Before applying the fade transition, you need to define the ImageView node for logoCar.bmp. For this, expand the Basic Shapes Palette and drag-and-drop the Image icon right below the create function definition. In the generated code, modify the URL to {__DIR__}img/logoCar.bmp and then place this code under a JavaFX variable as follows:

var logoCar = ImageView {
            image: Image {
                url: "{__DIR__}img/logoCar.bmp"
            }
        }
It is time to implement the fade transition (i.e., create a fade effect animation that spans the duration of the effect). Do this by updating the opacity variable of the node at regular intervals. Unfortunately, NetBeans Palette doesn't offer a set of transitions, so you have to insert one manually, like this:
FadeTransition {
        duration: 20s node: logoCar
        fromValue: 0.0 toValue: 1.0
        repeatCount:1 autoReverse: true
    }.play();
Finally, you add the logoCar Node in the default Group content. The final code of DeltaCarLogo.fx should be:
package deltacars;
 
import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.animation.transition.FadeTransition;
 
 // place your code here
public class DeltaCarLogo extends CustomNode {
 
    public override function create(): Node {
 
var logoCar = ImageView {
            image: Image {
                url: "{__DIR__}img/logoCar.bmp"
            }
        }
 
    FadeTransition {
        duration: 20s node: logoCar
        fromValue: 0.0 toValue: 1.0
        repeatCount:1 autoReverse: true
    }.play();
 
        return Group {
            content: [logoCar]
        };
    }
}

Creating the DeltaMenu.fx Class

As you can see from Figure 6, the DeltaMenu.fx class should provide a nice menu for your application. It's a little hard to explain its design in words, but the main idea is to display a menu made up of:
  • A set of six white rectangles using the fade transition (this time implemented for an array of Nodes)
  • A set of six Text nodes over these rectangles
  • A set of six "wheel" images, which use the path transition with a random cubic curve (the "wheel" image is named wheel.png and is stored in deltacars/img folder—see Figure 6.)



    Click here for larger image

    Figure 6: The DeltaMenu.fx Menu

In addition, when the cursor touches the rectangle, the corresponding "wheel" rotates 180 degrees once using a rotate transition.

Start by creating the DeltaMenu.fx class and then declaring the following set of variables:

var rectArray : Rectangle[];           //an array of Rectangle
var wheelArray : ImageView[];          //an array of ImageView
var pathArray : Path[];                //an array of Path
var tranArray : PathTransition[];      //an array of PathTransition
var ycoord=[180,220,260,300,340,380];  //an array of Integer

Next, add an array of six Rectangle nodes and implement mouse-click and mouse-enter events for every Rectangle. While you can add Rectangle nodes from the Basic Shapes Palette, you can add the mouse events from the Actions Palette using drag-and-drop. Encapsulating everything in a for statement, you should get something like this:

...
for (i in [0..5]) {
          insert Rectangle {
          x: 10,
          y: bind ycoord[i] - 10,
          width: 140,
          height: 20,
          arcWidth: 10,
          arcHeight: 10
          fill: Color.WHITE
 
          //on mouse clicked
         onMouseClicked: function( e: MouseEvent ):Void {
                println("Clicked on: {wheelArray[i]} ");
           }
 
          //on mouse enter
          onMouseEntered: function( e: MouseEvent ):Void {
 
 var rotTransition = RotateTransition {
              duration: 1s
              node: wheelArray[i]
              byAngle: 180
              repeatCount:1
              autoReverse: false
              }
          rotTransition.play();
          }
      } into rectArray;
     }
...
Next, add a fade transition for the above Rectangle array. You can insert one manually, like this:
...
for (i in [0..5]) {
       var fadTransition = FadeTransition {
        duration: 10s fromValue: 0.3 toValue: 1.0 node: rectArray[i]
        repeatCount:1 autoReverse: true
        }
     fadTransition.play();
     }
...
Now, define the wheelArray array elements. This array contains six ImageView nodes, as follows (use the Basic Shapes Palette to insert the ImageView node):
...
for (i in [0..5]) {
         insert ImageView {
                image: Image {
                    url: "{__DIR__}img/wheel.png"
                }
            } into wheelArray;
        }
...
Next, you have to define six Paths and store them in the pathArray array. Unfortunately, you can't add a Path through the Palette, so you have to insert them manually. After that, manually define six PathTransition elements (one for every Path) and "play" them:
...
for (i in [0..5]) {
           insert Path {
                 elements: [
                    MoveTo {
                        x: 700
                        y: rnd.nextInt( 450 ) },
                    CubicCurveTo {
                        controlX1: rnd.nextInt( 500 )
                        controlY1: rnd.nextInt( 500 )
                        controlX2: rnd.nextInt( 500 )
                        controlY2: rnd.nextInt( 500 )
                        x: 40
                        y: bind ycoord[i]
                    }
                ]
           } into pathArray;
        }
 
      for (i in [0..5]) {
          insert PathTransition {
                 duration: 20s
                 node: wheelArray[i]
                 path: AnimationPath.createFromPath(pathArray[i])
                 orientation: OrientationType.ORTHOGONAL_TO_TANGENT
                 repeatCount:1
                 autoReverse: false
          } into tranArray;
      }
 
      for (trans in tranArray) {
            trans.play();
      }
...

Finally, populate the default Group with the defined rectangles and "wheels," and add some text over the rectangles. Assembling everything and adding the corresponding imports, you should have the DeltaMenu.fx class in Listing 2.

Creating the DeltaAudioVideoPlayers.fx Class

You will complete the application by adding an audio/video player, as shown in Figure 7.



Click here for larger image

Figure 7: Adding an Audio/Video Player

The audio player's interface is made up of two buttons, play and stop. These are Swing buttons obtained from the javafx.ext.swing.SwingButton class. Both are decorated with two images encapsulated as SwingIcon objects (the play image is named play.png and the stop image is named end.png—both are stored in the deltacars/img folder). While you can add SwingButton from the Swing Components Palette, you must insert the SwingIcon manually.

The play button will call a JavaFX user-defined function named playMusic, while the stop button will call a user-defined function named stopMusic. These functions implement the audio player business logic using JMF (Java Media Framework) classes, so before implementing these functions, you have to add the jmf.jar library in the project classpath. JMF enables you to add audio, video, and other time-based media to applications and applets built on Java. Download the jmf.jar library and add it in the DeltaCars classpath as follows:

  1. In the Projects view, expand the DeltaCars node.
  2. Right-click on the Libraries node and select the Add JAR/Folder option from the contextual menu.
  3. In the file dialog window, navigate to the location of jmf.jar and press the Open button.

Now, the user-defined playMusic function should look like this:

...
var getplayerready=false;
var player: Player;
...
 
  function playMusic() {
    while(getplayerready == false)
     {
     var url = new URL("file:///C://JavaApplications//JavaFX//DeltaCars//song//demo.wav");
     var ml = new MediaLocator(url);
 
     player = Manager.createPlayer(ml);
 
     getplayerready = true;
 
     player.realize();
     player.start();
     }
}
...

The stopMusic function should look like this:

...
function stopMusic() {
    getplayerready = false;
    player.stop();
}
...

Author's Note: The demo.wav file is a sample audio file stored in the DeltaCars/song folder. Notice that the URL object indicates the absolute location. Modify it according to your configuration.

Next, create and add the two SwingButtons and two SwingIcons in the default Group, like this:

...
var btnPlay = Image {
    url: "{__DIR__}img/play.png"
    }
     var btnStop = Image {
    url: "{__DIR__}img/end.png"
    }
 
    var iconPlay =  SwingIcon {
        image: btnPlay
    }
 
    var iconStop =  SwingIcon {
        image: btnStop
    }
...
return Group {
   content: [
                SwingButton {
                    icon: iconPlay
                    translateX: 670
                    translateY:175
                    width:20
                    height:20
                    action: function() {
                        playMusic()
                    }
                }
                SwingButton {
                    icon:iconStop
                    translateX: 650
                    translateY:175
                    width:20
                    height:20
                    action: function() {
                    stopMusic()
                    }
                }
            ]
...

The audio player is ready. Now, you're ready to add the video player! You will use the JavaFX Media Player, a JavaFX component that embeds a resizable video playback window and a control bar that you can turn on and off. The control bar features a play/pause toggle, a progress indicator, the current playing position time, the total duration time, and a volume control. The JavaFX Media Player component is currently available as a binary file (you can find lib/mediacomponent.jar in the {NetBeans 6.5_HOME}/javafx2/javafx-sdk1.0/samples/SimpleVideoPlayer/webstart/lib folder; click here for a detailed tutorial about using the JavaFX MediaComponent). Add it to your project classpath in the same manner as you added the jmf.jar library.

Next, you have to define a MediaComponent instance like this:

...
    package var oxscale:Number = 10.0;
    package var mediaBox:MediaComponent = MediaComponent {
 
    // set the media and make the component visible
    mediaSourceURL : "file:///C://JavaApplications//JavaFX//DeltaCars//movie/demo.mpg"
    visible:true
 
    // the position and size of the media on screen
    translateX: bind 125+270-2.3*oxscale,
    translateY: 220,
    mediaViewWidth :  525,
    mediaViewHeight: 150
 
    // determines if the control bar is below the media or on top with a fade in
    staticControlBar: true
 
    // don't play the movie after is loaded
    mediaPlayerAutoPlay: false
 
    // set the volume
    volume: 1.0
};
...
Timeline {
            repeatCount: 1
            keyFrames: [
                KeyFrame {
                    time: 15s
                    canSkip: true
                    values: [
                        oxscale => 100 tween Interpolator.LINEAR
                    ]
                }
            ]
        }.play();
...

The code has a Timeline for the oxscale variable because your video player will use an OX translate from right to left.

Author's Note: The demo.mpg file is a sample video file stored in the DeltaCars/movie folder. Notice that the video location is indicated through absolute path. Modify it accordingly to your configuration.

Finally, surround the video player with a Rectangle node (the videoBorder variable). This node will appear on screen through a rotate and a scale transition (these kinds of transitions are available in Transformations Palette). These transitions will use the same Timeline as the MediaComponent.

Putting it all together, you will have the DeltaAudioVideoPlayers.fx class in Listing 3.

Add Created Nodes to Main.fx

The DeltaCars application is ready! However, nothing happens when you run it because the application nodes, DeltaTitleRect.fx, DeltaMenu.fx, DeltaCarLogo.fx, and DeltaAudioVideoPlayers.fx were not added to the Scene content. Therefore, the final version of Main.fx will look like this (notice how the MediaComponent is embedded in the scene):
package deltacars;
 
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.paint.Color;
import com.sun.fxmediacomponent.*;
import javafx.scene.Group;
 
Stage {
    title: "Delta Cars"
    width: 712
    height: 442
    resizable: false   
    
    scene: Scene {
        fill:Color.BLACK
        stylesheets: [
            MediaComponent.css_skins
        ]
        
        content: [ DeltaAudioVideoPlayers.mediaBox,DeltaMenu{},
                   DeltaTitleRect{},DeltaCarLogo{}, DeltaAudioVideoPlayers{}]
    }
}

Running the DeltaCars Application

There is no trick to running the DeltaCars application: just select the Run Main Project option from the Run main menu. The project will compile and you should see an explosion of effects, transitions, fades, and so on. When everything is settled, the application will look like Figure 1.

As you have seen, NetBeans 6.5 for JavaFX 1.0 is an elegant method for developing JavaFX projects. In this article you learned how to develop such a project using the NetBeans support and various JavaFX classes.

Code Download

  • DeltaCars.zip
  • For Further Reading

  • The complete JavaFX 1.0 API Documentation (from Sun Developer Network)
  • About the Author

    Anghel Leonard is a senior Java developer with more than 12 years of experience in Java SE, Java EE, and the related frameworks. He has written and published dozens of articles about Java technologies and two books about XML and Java (one for beginners and one for experts).

    Sitemap | Contact Us

    Thanks for your registration, follow us on our social networks to keep up-to-date