Module 1 Task 4: Incorporating Video


Launch JavaFX Media Browser Application Download NetBeans Project

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).

Architecture for Module 1 Task 3 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:

  1. Load the Module 1 Task 4 NetBeans project and open the NetBeans IDE.

  2. Run the project. As the project loads, observe that some placeholders and thumbnails have triangular play icons.

  3. Click a play icon to launch a video. Figure 2 shows the video running in the media component.

    Figure 2

  4. 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:

Source Code
     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.

Source Code
        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.

Source Code
    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.

Source Code
    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.

  1. In Constants.fx, change VIDEO_WATERMARK to a different URL.

  2. In Thumbnail.fx, change the value for opacity.

  3. Run the application, play a video, and see if you can detect the opacity change.


Rate This Article
Discussion

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 replies—your information is not used for any other purpose. By submitting a comment, you agree to these Terms of Use.

 

English
日本語
한국어
简体中文
русский
Português do Brasil