Module 1 Task 4: Incorporating Video
- Highlights
-
- Update the architecture to handle display and interaction with both images and video
- Extend a class you created yourself
- Use the as keyword to cast
- Call the MediaBox CustomNode to play video
Introduction
This task adds the ability to click a thumbnail on the wall to launch video. This tutorial uses the JavaFX Media Player component to support video playback.
The MetaData includes a new attribute for media type.
- If the media type is video, the placeholder is a video icon, and a
play watermark is overlaid on the image to indicate the media type.
Clicking a video icon launches it in the player utility.
- If the media type is image, the placeholder is an image icon. Clicking the image icon raises the full view.
In Figure 1 below you see loaded thumbnails and placeholders displayed as the wall loads – a plain rectangle for images, and a rectangle with a triangular play icon for video (as seen in the first three columns).
Figure 1
JavaFX Media Player Component
The JavaFX Media Player component makes it easy for you to embed video content in your applications. The component consists of a resizeable video playback window and a control bar that can be turned on and off. The control bar features include a play/pause toggle, a progress indicator, the current playing position time, the total duration time, and a volume control.
This component plays all cross-platform and native media formats currently supported by the JavaFX platform (see the Media support matrix for details). For instructions on how to encode your video content in the cross-platform format supported by JavaFX see How do you create and use cross-platform media with JavaFX technology?.
The JavaFX Media Player component is currently available as a binary file (you can find lib/mediabox.jar
in tutorial projects that play video). Source code for the JavaFX Media
Player component and detailed documentation will be made available at javafx.com soon.
Running the Project
Run the application to view the video feature:
- Load the Module 1 Task 4 NetBeans project and open the NetBeans IDE.
- Run the project. As the project loads, observe that some placeholders and thumbnails have triangular play icons.
- Click a play icon to launch a video. Figure 2 shows the video running in the media component.
Figure 2
- Click the player window to stop and close the player.
The Image behavior is the same as the previous task: Placing the mouse over a thumbnail enlarges the thumbnail. A click displays the image full view in the center of the wall, and a subsequent click on the scaled-up image hides it.
Architecture
The ability to categorize an object as video or media and handle it accordingly is new in this task. The architecture changes as shown in blue in Figure 3.
Figure 3
Media.fx, is a new base class for handling media. In
effect, it is everything that Photo used to be, except that it can
handle the display of images or video. Now Photo.fx and Video.fx extend the media class, so they deal only with tasks related to the specific media type. Photo.fx handles full view image display, and Video.fx manages playing video.
Note that Thumbnail.fx has one small change (adding the watermark). This is one of the advantages of an architecture such as this.
Integrating the Media Component
As discussed earlier the ability to support multiple media types requires some architecture changes.
Media.fx is a new CustomNode, but if you have been
following this tutorial the code is very familiar (most of the code was
take from the previous Photo.fx). This class defines the media
variable and a container for it. The container (the group) holds the
image or video, the label text, and the surrounding invisible rectangle
, which represents the total dimension of the media and its
decorations. Given this information the media can be accurately
positioned in the wall. The create() function call is in Media.fx:
init {
media = mediaBox
}
Note that Photo.fx and Video.fx don't use create(); they define media, then initialize with a similar call.
In MetaData.fx you can see the new variables created to support the media type. type_video, type_image, media_url, and media_type. As in earlier tasks the sample data is here to support testing, so it is not discussed.
Throughout this project past references to showPhoto() and hidePhoto() are now showMedia() and hideMedia(), and references to the variable photo now refer to the variable media.
You can see this in Main.fx,
where name updates account for most of the changes, and the only new
code is an if-then-else construct based on the media type. In the code
you can see that the if and else code is almost identical, the only
difference being the call to Photo.fx or Video.fx. For an explanation of this strategy, see the comments preceding the if() call.
Adding a Mouse Event (Click to Play)
Examine Video.fx to see how the player is launched
and stopped. While the video is playing, you can click the player and
it will close, similar to the way clicking the full view of an image
restores a view of thumbnails.
onMouseClicked: function(evt : MouseEvent) : Void {
(media as MediaBox).pause();
hide();
}
The above passage illustrates casting in JavaFX. The as keyword casts media to the mediaBox type. It calls pause() on the MediaBox and hides it.
Add a Watermark to the Video Thumbnail
Thumbnail.fx changes to add a watermark to a video
thumbnail. The Image placeholder attribute adds an if else construct to
display the placeholder according to media type.
Find def watermark: Node and review the code for ImageView.
def watermark: Node =
if (metaData.media_type == MetaData.type_video ) {
ImageView {
// Image.progress indicates how much of the image is loaded.
// Until the image is loaded, the watermark is transparent.
// Once the image is loaded, the watermark's opacity is set to 90%.
opacity: bind if ( image.progress == 100 ) .9 else 0
translateX: bind (boundingRect.boundsInLocal.width
- watermark.boundsInLocal.width)/2
translateY: bind (boundingRect.boundsInLocal.width
- watermark.boundsInLocal.height)/2
image: Constants.VIDEO_WATERMARK
}
} else {
// If the media is not a video, there is no watermark
null
}
Note the use of opacity and how it is tied to image.progress.
This behavior is difficult to see given when the test file is small
(the image and the watermark seem to load simultaneously). However,
without this code the watermark would show on the placeholder image.
Look at the create() function and the order of code in this Group.
protected override function create() : Node {
Group {
effect: if (reflect) then reflection else null;
content: [
boundingRect,
imageView,
watermark
]
}
}
Notice all the image scaling takes place before the watermark is applied, and the reflection effect is applied after the watermark has been added.
Try It
You can perform your own test of the watermark in the NetBeans project.
- In
Constants.fx, changeVIDEO_WATERMARKto a different URL. - In
Thumbnail.fx, change the value for opacity. - Run the application, play a video, and see if you can detect the opacity change.
We welcome your participation in our community. Please keep your comments civil and on point. You may optionally provide your email address to be notified of repliesyour information is not used for any other purpose. By submitting a comment, you agree to these Terms of Use.
