Effects Playground: Applying Filter Effects on Graphics
JavaFX provides a rich set of filter effects that includes blurs, shadows, color adjustments, warping, and much more. This sample demonstrates just how easy it is to apply these effects to your scene graph nodes and to adjust their settings dynamically.
Understanding the Code
The javafx.scene.effect package contains a number of commonly used filter effects, such as GaussianBlur and DropShadow, all of which derive from a common base class called Effect. Any graphical Node can have one or more Effects applied to it, simply by setting the Node.effect variable.
For example, adding a drop shadow to a circle node is very easy, as Figure 1 shows.
Circle {
centerX: 50
centerY: 50
radius: 25
effect: DropShadow { offsetX: 3 offsetY: 3 }
}
Figure 1: Applying an Effect to a Node
This sample application demonstrates 12 different Effect settings. To simplify the implementation, a class called EffectControl was created to group a thumbnail view of the current image, a bigger view of the image that is displayed on the upper portion of the Stage, and an Effect that is applied to each of these views. Figure 2 shows the code for these views.
package class EffectControl {
public var previewNode:Preview;
public var controlsGroup:Node;
public var canvasEffect:Effect;
public var canvasImage:Node = ImageView {
effect: bind canvasEffect
image: bind Main.fgImage
};
public var thumbEffect:Effect;
public var thumbImage:Node = ImageView {
effect: bind thumbEffect
image: bind Main.fgThumb
}
}
Figure 2: Binding the Effect
In addition, each subclass provides a group of controls, such as sliders and knobs, that are bound to the various properties of the Effect being manipulated. For example, the code snippet in Figure 3 demonstrates how a "static" MotionBlur effect is set up for the thumbnail view, and how the controls are bound to a more "dynamic" MotionBlur effect that is applied to the main canvas image.
package class MotionBlurControl extends EffectControl {
var slider:LabeledSlider;
var knob:LabeledKnob;
override public var canvasEffect = MotionBlur {
radius: bind if (slider.value < 1) 1 else slider.value
angle: bind knob.value
};
override public var thumbEffect = MotionBlur { radius: 5 angle: 45 };
override public var controlsGroup = Group {
content: [
slider = LabeledSlider {
translateX: 15
translateY: 22
text: "Radius"
minimum: 1
maximum: 63
value: 10
padding: 90
},
knob = LabeledKnob {
translateX: 320
translateY: 20
text: "Angle"
minimum: -90.0
maximum: 90.0
value: 45.0
minAngle: -90.0
maxAngle: 90.0
}
]
};
}
Figure 3: Binding the MotionBlur variables to Slider and Knob Controls
Note a couple of extras that the controls provide, thanks to the "magic" of the bind keyword. Anytime the slider thumb is moved or the knob control is turned, the MotionBlur instance is automatically updated, and the ImageView node to which it is attached is also automatically repainted. JavaFX runtime back-end processes attend to all the tedious details for you, such as efficiently repainting any updated nodes at the appropriate intervals.
As an aside, you might notice that this sample includes a number of bare-bones user interface controls in the effectsplayground.control package, such as Slider, Knob, Label, and RadioButton. The JavaFX 1.0 release includes only one control in the "common" profile (TextBox), but a forthcoming release will include many more. At some time in the future, this sample could be updated to use those new common controls instead of the handcrafted controls included here.
Chris CampbellStaff Engineer,
Sun Microsystems