In the Rolling Your Own JavaFX "Custom Nodes": A Graphical Menu Example post, I began showing you how to create your own UI controls in JavaFX. I also said that the JFX Custom Nodes category has been started in this blog in which custom nodes that you and I create will be featured.
Today's example features a simple custom node, named DeckNode, that I developed as a way to store a set of Node instances and display one of these nodes at a time. It is being used to augment the graphical menu example by showing the Node that pertains to a given menu button. Note that the concept is very similar to the Java CardLayout, so I wouldn't be surprised to see a similar class appear in the javafx.scene.layout package at some point. Just for grins, I provided the ability to specify a fade-in duration for the node being displayed. Here's a screenshot of the example application, with one of the nodes in the "deck" being displayed as the splash page:
One of the goals of JavaFX is for graphics designers and developers to be able to work together effectively in creating great looking applications. To demonstrate this, Mark Dingman (the User eXperience director at Malden Labs) created some graphical mock-ups for the fictitious CD application shown above. Future blog posts will turn these mock-ups into functioning pages using a combination of UI controls from the JavaFX SDK and custom nodes that we create in this blog. Here's an example mocked-up page in the form of a graphic that is being displayed as a result of pressing the Play button:
By the way, Malden Labs, under CTO Thom Theriault's technical leadership, has made a strong commitment to using JavaFX for some pretty exciting systems in the works. Anyway, if you would like to try today's example out, click on this Java Web Start link, keeping in mind that you'll need at least JRE 5. Also, installing Java SE 6 update 10 will give you faster deployment time.
Here's the code for the DeckNode class, contained in a file named DeckNode.fx:
/* * DeckNode.fx - * A node that shows a deck of nodes one at a time. * * Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com) * to demonstrate how to create custom nodes in JavaFX */ package com.javafxpert.custom_node; import javafx.animation.*; import javafx.lang.*; import javafx.scene.*; /** * A node that shows a deck of nodes one at a time. When the * visibleNodeId attribute is assigned a value, the Node whose * id is the same as the name becomes visible. Note that the * the id attribute of each Node must be assigned a unique name. * This class also has an attribute in which a fade-in duration * may be specified. */ public class DeckNode extends CustomNode { /** * A sequence that contains the Node instances in this "deck" */ public attribute content:Node[]; /** * An optional node that will appear in the background of all nodes */ public attribute backgroundNode:Node; /** * The id of the node that is to be visible */ public attribute visibleNodeId:String on replace { var nodes = for (node in content where node.id == visibleNodeId) node; visibleNodeRef = if (sizeof nodes > 0) nodes[0] else null; fadeTimeline.start(); } /** * The amount of time to fade-in the new Node */ public attribute fadeInDur:Duration = 1ms; /** * This attribute is interpolated by a Timeline, and the opacity * attribute of this DeckNode class is bound to it. This helps * enable the fade-in effect. */ private attribute opa:Number; /** * Override the opacity attribute so that it can be bound to the * opa attribute that is interpolated by a Timeline */ override attribute opacity = bind opa; /** * A Timeline to control the fade-in behavior */ private attribute fadeTimeline = Timeline { keyFrames: [ KeyFrame { time: bind fadeInDur values: [ opa => 1.0 tween Interpolator.LINEAR, ] } ] }; /** * A reference to the Node in the Node instances that is visible */ protected attribute visibleNodeRef:Node; /** * Create the Node */ public function create():Node { Group { content: bind [ backgroundNode, visibleNodeRef ] }; } }
Shown below is the main script for this program, in a file named DeckNodeExampleMain.fx:
/*
* DeckNodeExampleMain.fx -
* An example of using the DeckNode custom node. It also demostrates
* the MenuNode and ButtonNode custom nodes
*
* Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
* to demonstrate how to create custom nodes in JavaFX
*/
package com.javafxpert.deck_node_example.ui;
import javafx.application.*;
import javafx.scene.*;
import javafx.scene.geometry.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.text.*;
import javafx.scene.transform.*;
import java.lang.System;
import com.javafxpert.custom_node.*;
var deckRef:DeckNode;
Frame {
var stageRef:Stage;
var menuRef:MenuNode;
title: "DeckNode Example"
width: 500
height: 400
visible: true
stage:
stageRef = Stage {
fill: Color.BLACK
content: [
deckRef = DeckNode {
fadeInDur: 700ms
content: [
Group {
var vboxRef:VBox;
var splashFont =
Font {
name: "Sans serif"
style: FontStyle.BOLD
size: 12
};
id: "Splash"
content: [
ImageView {
image:
Image {
url: "{__DIR__}images/splashpage.png"
}
},
vboxRef = VBox {
translateX: bind stageRef.width - vboxRef.getWidth() - 10
translateY: 215
spacing: 1
content: [
Text {
content: "A Fictitious Audio Application that Demonstrates"
fill: Color.WHITE
font: splashFont
},
Text {
content: "Creating JavaFX Custom Nodes"
fill: Color.WHITE
font: splashFont
},
Text {
content: "Application Developer: Jim Weaver"
fill: Color.WHITE
font: splashFont
},
Text {
content: "Graphics Designer: Mark Dingman"
fill: Color.WHITE
font: splashFont
},
]
}
]
},
Group {
id: "Play"
content: [
ImageView {
image:
Image {
url: "{__DIR__}images/playlist.png"
}
}
]
},
Group {
id: "Burn"
content: [
ImageView {
image:
Image {
url: "{__DIR__}images/burning.png"
}
}
]
},
Group {
id: "Config"
content: [
ImageView {
image:
Image {
url: "{__DIR__}images/config.png"
}
}
]
},
Group {
id: "Help"
content: [
ImageView {
image:
Image {
url: "{__DIR__}images/help.png"
}
}
]
}
]
},
menuRef = MenuNode {
translateX: bind stageRef.width / 2 - menuRef.getWidth() / 2
translateY: bind stageRef.height - menuRef.getHeight()
buttons: [
ButtonNode {
title: "Play"
imageURL: "{__DIR__}icons/play.png"
action:
function():Void {
deckRef.visibleNodeId = "Play";
}
},
ButtonNode {
title: "Burn"
imageURL: "{__DIR__}icons/burn.png"
action:
function():Void {
deckRef.visibleNodeId = "Burn";
}
},
ButtonNode {
title: "Config"
imageURL: "{__DIR__}icons/config.png"
action:
function():Void {
deckRef.visibleNodeId = "Config";
}
},
ButtonNode {
title: "Help"
imageURL: "{__DIR__}icons/help.png"
action:
function():Void {
deckRef.visibleNodeId = "Help";
}
},
]
}
]
}
}
deckRef.visibleNodeId = "Splash";
Please notice the last line of the listing above is what causes the node that we named "Splash" to be displayed when the application starts.
The code for the other custom nodes used in this program (ButtonNode.fx and MenuNode.fx) are in the Rolling Your Own JavaFX "Custom Nodes": A Graphical Menu Example post, so you may want to visit that post. At some point I'll put these custom nodes in a JAR file if developers find them useful. As always, please leave a comment if you have any questions of comments!
Thanks,
Jim Weaver
Been in the web is very boring, what it make it good is find good places to read and useful tips like yours. Thanks
Posted by: generic viagra | May 13, 2010 at 06:59 PM
great screencast, thanks very much!!
instant degrees | affordable college degree | accredited life experience degree
Posted by: Zieg | October 08, 2009 at 07:03 AM
Great Post! Thanks
betsson
casino
Posted by: Guzelyorum | November 07, 2008 at 06:07 AM
Thanks your comment.
Posted by: Betsson | November 07, 2008 at 06:06 AM