TweetWallFX – Part 1

Hi,

It has been a while since I posted something on here. I think that everyone has heard about JavaFX and its recent updates. I had the chance to assist at the JavaFX session done by Nicolas Lorain, Jean-François Denise and Eric Le Ponner (working at Oracle) at Devoxx France in April 2012 and then to talk to these guys. What a great meeting, such interesting people and such a promising technology. Well maybe you’re already familiar with JavaFX 1.3, or maybe like me you’ve looked at it and didn’t want to learn some another new scripting language. Personally JavaFX 1 wasn’t interesting for me for the simple reason that it wasn’t possible to use external JARs file, like a JDBC driver. But now, all of this goes away because JavaFX 2.1 has been released (you can download it here) and I really have to admit: I’m confident about it. Because I wanted to start learning this new technology I decided to create an application build with JFX. So I decided to create a tweet wall application and share with you my experiences, my learnings and my enthusiasm. Well, the functionality of the application is to basically display tweets with a specific hashtag. So pretty straight forward. Currently the application is far away not finished and that’s the reason why there will be more posts about it.

Ok, let’s go …

Swing is dead !! Long live JFX

Until now, we have to admit that building desktop applications in Java was pretty hard. Swing is currently an old technology, even if it still works well. But developing in Swing is pretty long and you can not use it to do some rad (rapid application development) in order to quickly have a poc (proof of concept) of the UI (user interface). In Swing I usually had two mains problems:

  • 1. Positioning: it was terribly awful to get a correct UI with your components placed where you want to, reacting correctly when the window’s size changed and so on
  • 2. EDT: the Event Dispatch Thread was typically hard to manipulate, especially when you were using some custom painting! (Do you remember how many times you tried to understand which repaint() method you had to call? On which component?)

Now this is said, let’s focus a bit on JavaFX. JFX 2 introduced FXML which is a scriptable, XML-based markup language. It is used to create your graph of objects in order to build your UI. It is the same concept that Microsoft used in WPF called XAML. So maybe you’re wondering what a graph of objects is. If you’re familiar with the JSF technology, you probably know about the concept UI View, that contains all components displayed in your JSF pages. Well FXML is globally the same concept: you put all components (that have a “representation” in FXML) of your UI in a XML file. Like JSF pages, you can also use the Expression Language (EL) in your FXML markups, as well as some JavaScript scripts. And what is very interesting is that you can use some CSS properties on your components in order to create an attractive UI. Finally one important thing to say is that you can bind components of your FXML file to a component in a backing bean for various reasons and I will explain some of them in time. As you can see, all of these concepts are not really new in our Java world, you just have to take a look at JSF.

Also, what is very important about FXML is that for the first time in Java desktop application we can do real MVC. Indeed, just let be honest: how did you do real MVC in Swing? Yeah you created a package for your graphical components, another one for your listeners and so one. And because sometimes we were so lazy we mixed the listeners classes in the components classes… Well forget about that. With FXML you can completely separate the view layer from the controller.

Start screen

After this brief introduction, let’s see the first screen we’re going to create for our application: a start screen allowing us to specify which hashtag to create a “wall” for it. For now we’re going to use these “visible” components:

  • A label for displaying to enter a hashtag
  • A text field for entering the hashtag
  • A search button

Well, after creating a new JavaFX project in your favorite IDE (I currently use NetBeans) you will have a main class launching the application and a FXML file. We are going to modify this file in order to create a UI for that screen.

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="mainPanel" fx:id="anchorPane" prefHeight="768" prefWidth="1024" xmlns:fx="http://javafx.com/fxml" fx:controller="com.twasyl.tweetwallfx.controllers.TweetWallFXController">
    <children>
        <TabPane id="tabPane" fx:id="tabPane" >
            <tabs>
                <Tab closable="false">
                    <text>Start</text>
                    <content>
                        <VBox fx:id="searchForm" alignment="CENTER" spacing="10" prefHeight="768" prefWidth="1024">
                            <children>
                                <HBox alignment="CENTER">
                                    <children>
                                        <Label id="hashtagLabel" text="Enter the hashtag to look for: "/>
                                        <TextField id="hashtagTextField" fx:id="hashtagTextField" promptText="#" prefWidth="200" />  
                                    </children>
                                </HBox>
                                <Button id="button" text="Search" onAction="#startTweetWall"  />
                            </children>
                        </VBox>
                    </content>
                </Tab>
            </tabs>
        </TabPane>
    </children>
</AnchorPane>

Well let’s get some explanations. You can see that the root element of the document is which is a region into which you can add multiple components. The markup has several attributes that are pretty easy understand except maybe the fx:controller. This tag has a value which is a FQCN (full qualified class name). This attribute allows you to bind your current FXML file to a backing class that will be use as controller. And what is a controller? It is a class that can contain methods that will be called when a button is pressed for example, or a binding to some components of you FXML file to a class. I’m sure you’re wondering how the binding is done. Well it is done using the fx:id which value must be strictly equal to the name of a component in your backing class, annotated with @FXML. Example: my AnchorPane here has th fx:id=”anchorPane”. So in my class defined by the fx:controller attribue I have this:

public class TweetWallFXController implements Initializable {

    @FXML
    private TabPane tabPane;
    @FXML
    private TextField hashtagTextField;
    @FXML
    private Pane anchorPane;

    @FXML
    private void startTweetWall(ActionEvent event) {
        // ...
    }

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
    }
}

The I use a TabPane with some tabs. And the first tab contains some layout components (VBox, HBox) used to place my Label, TextField and Button on the screen. What I would like to explain is the onAction attribute of my Button. Indeed the value is #startTweetWall which refers to a method named startTweetWall annotated with @FXML in my controller class (defined in the fx:controller attribute of my AnchorPane). The # indicates you’re referring a method. Well this FXML gives you this screen:

Not very beautiful… Let’s just modify our components by adding some style.

<HBox alignment="CENTER">
  <children>
    <Label id="hashtagLabel" text="Enter the hashtag to look for: " style="-fx-font-size: 25pt;"/>
    <TextField id="hashtagTextField" fx:id="hashtagTextField" promptText="#" prefWidth="200" style="-fx-font-size: 20pt;" />
  </children>
</HBox>
<Button id="button" text="Search" onAction="#startTweetWall" style="-fx-font-size: 20pt;" />

As you can see, every style property used by JFX is prefixed by -fx-. And these modifications give us this screen:

Now, why not adding some background gradient? Let’s go! I surround my components by another AnchorPane.

...
<AnchorPane style="-fx-background-color: linear-gradient(#69B4E4 0%, #0070B9 100%);">
  <VBox fx:id="searchForm" alignment="CENTER" spacing="10" prefHeight="768" prefWidth="1024">
    <children>
      <HBox alignment="CENTER">
        <children>
          <Label id="hashtagLabel" text="Enter the hashtag to look for: " style="-fx-font-size: 25pt;" />
          <TextField id="hashtagTextField" fx:id="hashtagTextField" promptText="#" prefWidth="200" style="-fx-font-size: 20pt;" />  
        </children>
      </HBox>
      <Button id="button" text="Search" onAction="#startTweetWall" style="-fx-font-size: 20pt;" />
    </children>
  </VBox>
</AnchorPane>
...

Look at the -fx-background-color style. You can use a function named linear-gradient and pass to it any number of colors you want your gradient to be composed of! The percentage is where the color begins or ends (depending if it is the first argument).

Looks better. Let’s add an icon (users love icons).

...
<AnchorPane style="-fx-background-color: linear-gradient(#69B4E4 0%, #0070B9 100%);">
  <ImageView id="twitterSticker" fitWidth="128" fitHeight="128" layoutX="30" layoutY="30">
    <image>
      <Image url="@/com/twasyl/tweetwallfx/resources/images/twitterSticker.png" />
    </image> 
  </ImageView>
  <VBox fx:id="searchForm" alignment="CENTER" spacing="10" prefHeight="768" prefWidth="1024">
    ...
  </VBox>
</AnchorPane>

We’re using an ImageView placed at 30px from the top and left corner, with a size of 128px. You specify the image by using the Image markup to indicates which image you would like to load using the url attribute. Starting the value value with a @ means that the image location is not relative to the current location of the FXML file.

And now, the name of the application.

...
<ImageView id="twitterSticker" fitWidth="128" fitHeight="128" x="30" layoutY="30">
  ...
</ImageView>
<Label text="TweetWallFX" prefWidth="1024" style="-fx-font-size: 100pt; -fx-text-fill: white; -fx-font-weight: bold;" alignment="CENTER" layoutY="30" />
...

Don’t you think this title is a bit “simple”? Well let’s add some effects really simply!!

...
<Label text="TweetWallFX" prefWidth="1024" style="-fx-font-size: 100pt; -fx-text-fill: white; -fx-font-weight: bold;" alignment="CENTER" layoutY="30">
  <effect>
    <DropShadow offsetY="5" offsetX="5" color="GRAY">
      <input>
        <Reflection fraction="0.7" topOffset="-20" />
      </input>
    </DropShadow>
  </effect>
</Label>
...

As you can see, we use the effect markup in order to add one effect to the label. If you want to add more effects, some have an input in order to chain effects. That is the reason why you first create the DropShadow effect that contains the Reflection one. And the final result is:

Well that’s it for this post. As you can see, everything that has been done uses FXML. No other code!! You can see how powerful and convenient FXML is. And the best way to know how to use it is to read the documentation, which contains plenty of information!

Stay tuned for next part !!

5 Responses to TweetWallFX – Part 1

  1. Pingback: JavaFX links of the week, May 14 // JavaFX News, Demos and Insight // FX Experience

  2. Pingback: Java desktop links of the week, May 14 | Jonathan Giles

  3. ffesseler says:

    Too bad there is no autocompletion yet for FXML files, which makes writing your UI a real pain. (especially for someone with a Flex background like me).

    I’ve read autocompletion for FXML will come with NetBeans 7.2 though.

    But I agree, there is potential for building desktop apps with JavaFX 2.0, with its new API and now that Flex & Silverlight are left out in the cold

  4. Thierry WASYL says:

    Well, you can use SceneBuilder (http://www.oracle.com/technetwork/java/javafx/tools/index.html) if you don’t want to type the FXML code. You can use it to build your UI and then export the FXML that will almost be ready to be integrated in your project.
    But I agree that autocompletion is very helpful. Currently it’s not completely missing in NetBeans: sometimes I get it on some attributes, but not always … Strange.

  5. Pingback: TweetWallFX – Part 2 « Thierry WASYL : Java blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: