Archive for the ‘Twitter API’ Category

Tutorial on how to use JavaFX 1.3 with the Twitter API

June 7, 2010

I thought I would put together a basic tutorial, showing JavaFX in action with the Twitter API (utilising Twitter4J). The app will resolve your Twitter followers, show your timeline, and send a tweet.

In the first instance you need to download the latest Twitter4J library. I use NetBeans and so I added Twitter4J to the new project I created for this tutorial. Under the properties, right click, select properties, then select library. Then add the jar file you downloaded.

Ok, with that done, we can start coding. First off we want to create a Java class file, lets call it MyTwitterReader:

public class MyTwitterReader
{
    private Twitter myTwitter;
    private String timeLine;
    private String followersURL;
    private IDs myFollowerIds;

    public MyTwitterReader()
    {
        myTwitter = new Twitter("your Twitter username","your Twitter password");
    }

    public String getTimeline()
    {
        try
        {
            List myTimeline = myTwitter.getUserTimeline();
            for (Status status : myTimeline)
            {
                timeLine = timeLine + status.getText() + '\n';
            }

        }
        catch (Exception e)
        {
            System.err.println("Error! "+e.toString());
        }
        finally
        {
            return timeLine;
        }
    }

    public String getFollowersURLs()
    {
        followersURL = new String();
        try
        {
            myFollowerIds = myTwitter.getFollowersIDs();
            int[] t = myFollowerIds.getIDs();
            for (int i = 0; i < t.length; i++)
            {
                String id = String.valueOf(t[i]);
                User tu = myTwitter.showUser(id);
                followersURL = followersURL + tu.getProfileImageURL() + '\n';
            }
        }
        catch (Exception e)
        {
            System.err.println(&quot;Error! &quot;+e.toString());
        }

        finally
        {
            return followersURL;
        }
    }

    public void sendMessage(String tweet)
    {
        try
        {
            myTwitter.updateStatus(tweet);
        }
        catch(Exception e)
        {
            System.err.println("Error! Failed to send "+e.toString());
        }
    }

}

The first thing to note is we are hard-coding the username and password within the constructor, if you want you can write a new constructor which takes the username and password which have been provided by the UI (but that isn’t for this tutorial). I have also created two methods, getTimeline and getFollowersURLs. These will be used to populate the relevant lists in the UI. Further to this, there is the method sendMessage(tweet) which will be called when we want to Tweet to the rest of the world!

The Twitter object, myTwitter is used to gain access to the Twitter data. In the case of getTimeline, we call the getUserTimeline() method which returns a List of Status objects. I then go through each of these and write to a String object and pass this back (in our case JavaFX). The method getFollowersURLs() calls getFollowersIDs(), which returns an IDs object, I then put this into an array of int, and loop through each value converting the value to a String and passing this to showUser method. This method returns a Twitter User object, from which I can ascertain the Profile Image URL using the method getProfileImageURL() on each Twitter User object.

You still with me? Cool.

Let moves onto the “exciting” bit, the user interface. First things first, I am not a designer and this is a simple tutorial so bear with me on the “look and feel”, of course you can do what you want 🙂

Ok, so the UI will contain the Timeline, your followers pictures, and a input box in which you can type your tweet, oh and a button to send the tweet, this is how I have laid it out:

Ok, so a quick overview of the UI.

  1. You will notice the Tweet button is “greyed” out, this will change once some data is entered.
  2. The Characters remaining will count down with each character we enter.
  3. Both My Followers and My Tweets are empty (well we haven’t coded it all up yet!)
  4. Do you like my choice of colours, very original!

I hope this is ok, now over to the code. In the first instance, I like to encapsulate this in a class rather than have it all in the Main.fx file. So we will create a JavaFX class instance, call it TwitterOverview, below is the code:

public class TwitterOverview extends CustomNode
{
    package var processTweet : function(s: String):Void;
    package var timeLine: String;
    package var followersURL: String;

    var tweet : String;
    var items : String[];
    var followerURLs: String[];

    var tweetInput : TextBox = TextBox
    {
       //styleClass: "twitterOverviewTweetInputText"
       columns: 40
       selectOnFocus: true
       translateY: 40;
       translateX: 120;
    }

    var tweetLength : Integer = bind (140 - tweet.length());

    def tweetButton : Button = Button
    {
       //styleClass: "twitterOverviewTweetButton"
       translateY: 38;
       translateX: 450;
       text: "Tweet";
       disable: bind if (tweetInput.rawText.length() < 140 and tweetInput.rawText.length() > 0) false else true;
       action: function()
       {
          processTweet(tweetInput.text);
          tweetInput.text = "";
          tweet = "";
       }
    }

    package var twitterPersonalTimelineLV : ListView = ListView
    {
       //styleClass: "TwitterOverviewTimeLine"
       translateX: 40;
       translateY: 120;
       layoutInfo: LayoutInfo
       {
          height: 450;
          width: 450;
       }
    }

    package var myFollowers : ListView = ListView
    {
       //styleClass: "TwitterOverviewMyFollowersList"
       translateX: 510;
       translateY: 90;
       layoutInfo: LayoutInfo
       {
          height: 350;
          width: 60;
          margin: Insets
          {
             top: 50
             bottom: 50
             left: 50
             right: 50
          }
       }
    }

    function setup():Void
    {
       items = timeLine.split('\n');
       followerURLs = followersURL.split('\n');

       if (twitterPersonalTimelineLV.items.size() > 0)
       {
          delete twitterPersonalTimelineLV.items;
       }

       for (i in [1..<items.size()])
       {
          insert items[i] into twitterPersonalTimelineLV.items;
       }

       if (myFollowers.items.size() == 0)
       {
          for (i in [0..<if (followerURLs.size() < 10) followerURLs.size() else 10])
          {
              insert
              ImageView
              {
                  fitHeight: 50;
                  fitWidth: 50;
                  image: Image { url: followerURLs[i];}
              }
              into myFollowers.items;
          }
       }
    }

    var screen2 : Group = Group
    {
       content:
       [
          Label
          {
             //styleClass: "TwitterOverviewMyTweets"
             text: "My tweets:"
             translateX: 40;
             translateY: 100;
          },
          twitterPersonalTimelineLV,
          Label
          {
             //styleClass: "TwitterOverviewMyFollowers"
             text: "My Followers:"
             translateX: 510;
             translateY: 70;
          },
          myFollowers,
          Label
          {
             //styleClass: "TwitterOverviewSendTweet"
             text: "Send a Tweet"
             translateX: 30;
             translateY: 40;
          },
          tweetInput,
          tweetButton,
          Label
          {
             //styleClass: "TwitterOverviewCharsRemaining";
             text: bind "Characters remainding {(140-tweetInput.text.length())}"
             translateX: 340;
             translateY: 70;
          }
       ]
    }

    override function create():Group
    {
       setup();
       return screen2
    }
 }

Ok, a few comments to make about this code:

  1. You will notice the commented lines styleClass – This is for the CSS styling. I won’t cover this here.
  2. If you look at the tweetButton code, you will see it is disabled = true if the text within the TextBox (tweetInput) is 0 or greater than 139. This means the button is enabled when you start typing.
  3. The same applies to the text counting down the number of characters, notice we are using rawText.length() to ascertain this.
  4. I hold my hands up to using X / Y positioning, rather than VBox, HBox etc, I know Amy Fowler won’t be happy! 🙂 It was just what I did at the time, and I am being lazy by not changing it. Apologies!
  5. The only other thing worth commenting on is, I have the function to process sending a tweet in Main.fx (we shall move onto that next).

Now it gets exciting…. We move onto Main.fx. As we laid out the UI in the TwitterOverview class, the main.fx is clean and tidy (just the way I like it):


       var fxTwitter: MyTwitterReader = new MyTwitterReader();

       function processTweet(tweet: String):Void
       {
            fxTwitter.sendMessage(tweet);
       }

       var myTwitterOverview : TwitterOverview = TwitterOverview{processTweet: processTweet; followersURL: bind fxTwitter.getFollowersURLS(); timeLine: bind fxTwitter.getTimeline();};

       Stage 
       {
             title: "Application title"
             scene: Scene
             {
                    width: 600
                    height: 600
                    content: 
                    [
                          myTwitterOverview
                    ]
             }
       }

That’s it!!! Fire it up and send me a Tweet 🙂 (@SmeeZee)

Going forward, you might want to play with CSS styling, or perhaps explore the additional functionality available through Twitter4J. Perhaps you want the Timeline to update every X seconds? Have a play, let me know what you do. Of course my style is evident in this code, if it goes against yours I am sure you can get my drift and can code up your own JavaFX Twitter client.

Ha fun.

Advertisements