Tag Archives: RIA

FootprintFX

Footprint logo

Footprint is a publisher and distributor of certificates of participation in conferences – signed PDF documents that prove you attended a conference or a course.

This is a little JavaFX application that shows how to create a interface that displays data provided by services. This version uses three services: one that counts the number of users, other that counts the number of events and one that list these events. Check out the source code here.  Try the application as a draggable JavaFX applet here.

JavaFX 1.1 for Linux workaround

Download

javafx4linux.tar.bz2 (~ 36Mb).

Installing

1) Extract the javafx4linux.tar.bz2 file. In this example I’m placing it on my Desktop. After the installing process you can remove it.

javafx linux ubuntu extract

2) Open your NetBeans 6.5 and go at ToolsPlugins and go to Downloaded tab. In a plain and new NetBeans installation there will be no plugin in this tab yet.

netbeans javafx linux step01

netbeans javafx linux step02

netbeans javafx linux step03

3) Click on the Add Plugins button and head to the directory you extracted the file and select all .nbm files.

netbeans javafx linux step 04

4) You will see a list of 22 plugins selected. Click on the Install button.

netbeans javafx linux step 05

5) Just keep clicking on the Next button.

netbeans javafx linux step 6

6) Check the license agreement accept box.

netbeans javafx linux step 7

7) You’ll see a warning because the Linux pluggin is not signed. Don’t worry, just click Continue.

netbeans javafx linux step 8

8) Click on Finish to restart NetBeans.

netbeans javafx linux step 9

9) Now we can test it. Go at FileNew Project, select the JavaFX on Categories and JavaFX Script Application on Projects.

netbeans javafx linux step 10

10) Put some code and run it. There is. JavaFX on Linux.

netbeans javafx linux step 11

Considerations

This is not a official of JavaFX for Linux! This solution was tested on Ubuntu 9.04 “Jaunty Jackalope” with Java 6 update 13 and NetBeans 6.5.1, but should also work with others Linux distributions and Java versions greater than 5.

Known bugs

As a non official workaround for JavaFX for Linux you may notice some drawbacks. Some parts of the JavaFX runtime rely on native implementations on the specific operational system. You may not use some multimedia capabilities as video playback, JavaFX Mobile emulator and some performance issues in some effects. Despite that, is perfectly possible to develop applications using JavaFX on NetBeans.

Thanks

I’d like to thanks some guys around the world. Weiqi Gao’s original post on JavaFX on Linux, HuaSong Liu article on DZone and Kaesar Alnijres post.

JavaFX, easy use of tiles

Continuing my little JavaFX framework for game development, right now focused on use those tiles I’m drawing and posting here in my blog. This framework will be a group of classes for simplify and hide some complexities of common game development. Right now I wrote just a few of them.

Use

We create a tileset from the files.png file that way

var tileset = Tileset {
    cols: 15 rows: 10 height: 32 width: 32
    image: Image {
        url: "{__DIR__}tiles.png"
    }
}

tiles

Tileset are orthogonal, distributed into a grid of cols columns and rows rows. Each tile have dimensions height x width.

A Tileset is used into a Tilemap

var bg = Tilemap {
    set:tileset cols:5 rows:5
    map: [8,8,8,8,8,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]
}

That shows

bg tilemap

Each number in the map represents a tile in the tilemap. Number 0 means the first tile at the upper left corner, numbers keep growing from left to right columns, from top to bottom rows.

Another example

var things = Tilemap {
    set:tileset cols:5 rows:5
    map: [80,55,56,145,145,96,71,72,61,62,0,0,0,77,78,122,0,0,93,94,138,0,0,0,0]
}

things tileset

A tilemap can also contains more than one layer

var room = Tilemap {
    set:tileset cols:5 rows:5 layers:2
    map: [
        [8,8,8,8,8,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],
        [80,55,56,145,145,96,71,72,61,62,0,0,0,77,78,122,0,0,93,94,138,0,0,0,0]
    ]
}

tileroom

Implementation

The Tileset class basically stores a Image and a collection of Rectangle2D objects, for be used as viewports in ImageView classes.

import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.geometry.Rectangle2D;
 
public class Tileset {
    public-init var      image: Image;
    public-init var      width: Integer = 32;
    public-init var     height: Integer = 32;
    public-init var       rows: Integer = 10;
    public-init var       cols: Integer = 15;
    protected   var       tile: Rectangle2D[];
 
    init {
        tile =  for (row in [0..rows]) {
            for (col in [0..cols]) {
                Rectangle2D{
                    minX: col * width, minY: row * height
                    height: width, width: height
                }
            }
        }
    }
}

The Tilemap is a CustomNode with a Group of ImageViews in a grid. The grid is mounted by iterating over the map as many layers was defined.

public class Tilemap extends CustomNode {
    public-init var   rows: Integer = 10;
    public-init var   cols: Integer = 10;
    public-init var    set: Tileset;
    public-init var layers: Integer = 1;
    public-init var    map: Integer[];
 
    public override function create(): Node {
        var tilesperlayer = rows * cols;
        return Group {
            content:
                for (layer in [0..layers]) {
                    for (row in [0..rows-1]) {
                        for (col in [0..cols-1]) {
                            ImageView {
                                image: set.image x: col * set.width y: row * set.height
                                viewport: set.tile[map[tilesperlayer*layer + row*rows+col]]
                            }
                        }
                    }
                }
        };
    }
}

Next steps

  • Integrate to a map editor
  • Support some XML map format
  • Sprite classes for animation
  • Integrate those collision detection classes I posted before

Download

Reading Twitter with JavaFX

twitter bird

Twitter is a social network and micro-blogging service that allow you to create and read tweets, 140 characters text-based posts. It’s becoming a popular tool to keep in touch with your friends, coworkers, bloggers, etc. Here we’ll create a very simple application that show us tweets related with a given word.

Twitter offers a very simple and powerfull REST API which supports XML, JSON, and the RSS and Atom formats. As we are aiming just to read tweets we’ll use just the Search API.

We do that in three steps:

  1. Query Tweets
  2. Parser the Atom result
  3. Show tweets into a GUI

Let’s see them in the order of dependence beetween them.

Displaying a Tweet

var gradient = LinearGradient {
    startX: 0.0,
    startY: 0.0,
    endX: 0.0,
    endY: 150.0
    proportional: false
    stops: [Stop {offset: 0.0 color: Color.DARKGRAY },
        Stop { offset: 1.0 color: Color.BLACK }]
}
 
public class Tweet extends CustomNode {
    public var image: Image;
    public var username: String;
    public var message: String;
    public override function create(): Node {
        var txt = Text {
            x: 65  y: 35 wrappingWidth: 150 fill: Color.WHITE
            content: "{message}"
        }
        return Group {
            content: [
                Rectangle {
                    width: 220 height: txt.boundsInLocal.height + 40
                    arcHeight: 10 arcWidth: 10 fill: gradient
                },
                ImageView {
                    x: 5 y: 20 image: image
                },
                Text {
                    x: 65  y: 20 fill: Color.BLACK content: "{username} said"
                },
                txt
            ]
        };
    }
}

For example, this tweet would become:

tweet example

Parsing ATOM result

In my last post about JavaFX I showed how to parse XML documents (and make sandwiches) with JavaFX. Here we’ll use the Atom format, but use any other would be almost the same. Parsing XML or JSON documents with JavaFX is both very simple using the javafx.data.pull.PullParser class.

A query output is a Atom XML document with several information. We are interested only in the fields that holds the avatar image, the message and the user name.

var tweets = VBox {}
def parser = PullParser {
    var avatar;
    var firstname;
    var text;
    documentType: PullParser.XML;
 
    onEvent: function(event: Event) {
        if(event.type == PullParser.START_ELEMENT){
            if(event.qname.name.equals("link")){
                if(event.getAttributeValue(QName{name: "rel"}) == "image"){
                    avatar = event.getAttributeValue(QName{name:"href"});
                }
            }
        }
 
        if(event.type == PullParser.END_ELEMENT) {
            if(event.qname.name == "title"){
                    text = event.text;
            }
            if((event.qname.name == "name")and(event.level==3)){
                var names: String[] = event.text.split(" ");
                firstname = names[0];
                insert Tweet {
                        image: Image {
                            url: avatar
                        }
                        message: text
                        username: firstname
                    } into tweets.content;
            }
        }
    }
}

Querying Tweets

We can get Atom results through url queries like that:

Notice that queries should be URL encoded. We will use a additional parameters &rpp=4 to receive only 4 results per page. To know more about search queries read the Search API Documentation. We get these results as InputStreams making asynchronous HTTP requests using the javafx.io.http.HttpRequest class, which it’s perfect to invoke RESTful Web Services.

word = "Beatles";
var request = HttpRequest {
    location: "http://search.twitter.com/search.atom?q={word}&rpp=4";
    onInput: function(stream: java.io.InputStream) {
        parser.input = stream;
        parser.parse();
    }
}
request.enqueue();

Conclusion

Here is the application running for the word “House”.

twitter with javafx

Is not a complete Twitter client, as it’s not intended to be, but can show you how to handle a simple asynchronous call and handle Twitter documents. There’s already a few beta JavaFX Twitter clients like Tweetbox and Twitterfx and certanly others will appears.

Download

Sources and Netbeans project, fxtwitter.tar.bz2.

Parsing a XML Sandwich with JavaFX

delicious sandwich

Let sandwich.xml be a file at /tmp directory with the content above.

<?xml version="1.0" encoding="UTF-8"?>
 
<bread sesame="true">
   <catchup/>
   <hamburguer/>
   <cheese type="chedar"/>
   <maionese/>
   <lettuce/>
</bread>

We can open it using java.io.FileInputStream and so use it on a javafx.data.pull.PullParser. A PullParser is a event oriented parser that works with XML and YAML files. Above a general and simple parser with a GUI that show the list of events during the parse process.

import java.io.FileInputStream;
import javafx.data.pull.Event;
import javafx.data.pull.PullParser;
import javafx.ext.swing.SwingList;
import javafx.ext.swing.SwingListItem;
import javafx.scene.Scene;
import javafx.stage.Stage;
 
var list = SwingList { width: 600 height: 300 }
 
var myparser = PullParser {
   documentType: PullParser.XML;
   onEvent: function (e: Event) {
      var item = SwingListItem {
         text: "event {e}"
      };
      insert item into list.items;
   }
   input: new FileInputStream("/tmp/sandwich.xml");
}
myparser.parse();
 
Stage {
   title: "XML Sandwich"
   scene: Scene { content: list }
}

javafx xml sandwich

The XML cheese element produce two the outputs.

type:1 typeName:START_ELEMENT level:1 qname:cheese text:” namespaces:{} attributes:{type=chedar}
type:2 typeName:END_ELEMENT level:1 qname:cheese text:” namespaces:{} attributes:{type=chedar}

Notice that white spaces like tab and escape characters like new line also produced events from type TEXT. We are not interested on them. Above a parser that looks only those events of type START_ELEMENT or END_ELEMENT, look into it’s contents, building a sandwich at runtime based on the XML file.

import java.io.FileInputStream;
import javafx.data.pull.Event;
import javafx.data.pull.PullParser;
import javafx.data.xml.QName;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.scene.Scene;
import javafx.stage.Stage;
 
// my sandwich starts as an empty VBox
var mysandwich = VBox {}
 
// give a name and returns a ImageView with a png image like the name
function ingredient(name){
   return ImageView {
      image: Image {
         url: "{__DIR__}{name}.png"
      }
   }
}
 
// basicaly, look the event and put a ingredient at mysandwich
var myparser = PullParser {
   documentType: PullParser.XML;
   onEvent: function (e: Event) {
      // starter xml elements
      if(e.type == PullParser.START_ELEMENT){
         // bread
         if(e.qname.name.equals("bread")){
             insert ingredient("bread_top") into mysandwich.content;
         }
 
         // hamburguer
         if(e.qname.name.equals("hamburguer")){
             insert ingredient("hamburguer") into mysandwich.content;
         }
 
         // catchup
         if(e.qname.name.equals("catchup")){
             insert ingredient("catchup") into mysandwich.content;
         }
 
         // maionese
         if(e.qname.name.equals("maionese")){
             insert ingredient("maionese") into mysandwich.content;
         }
 
         // lettuce
         if(e.qname.name.equals("lettuce")){
             insert ingredient("lettuce") into mysandwich.content;
         }
 
         // cheese
         if(e.qname.name.equals("cheese")){
            var type= e.getAttributeValue(QName{name:"type"});
            if(type.equals("cheedar")){
                 insert ingredient("cheedar") into mysandwich.content;
            } else {
                insert ingredient("cheese") into mysandwich.content;
            }
         }
      }
 
      // ending xml elements (just bread)
      if(e.type == PullParser.END_ELEMENT){
         if(e.qname.name.equals("bread")){
            insert ingredient("bread_botton") into mysandwich.content;
         }
      }
   }
   input: new FileInputStream("/tmp/sandwich.xml");
}
myparser.parse();
 
Stage {
   title: "XML Sandwich"
   scene: Scene {
      height: 300
      content: mysandwich
   }
}

Here’s our sandwich.

sandwich javaFX

Just changing the XML file you got a new sandwich.

<?xml version="1.0" encoding="UTF-8"?>
<!-- double burger -->
<bread sesame="true">
   <maionese/>
   <lettuce/>
   <hamburguer/>
   <cheese type="chedar"/>
   <catchup/>
   <hamburguer/>
   <lettuce/>
</bread>

double burguer

Bon appétit.

For more details on XML and JSON parsing see the JavaFX API.

Gravatar with JavaFX

Gravatar is easy way to put global recognized avatar images into any Internet application. Gravatar would stands for globally recognized avatar.

Below,  the Java class that I got from the Gravatar Java reference. Here is a static class called md5 that applies a MD5Sum algorithm over a string. Is a little complex code but all behavior keeps encapsulated and who uses it don’t need to know how it works. Just gives a string and receives a encrypted string. Those two codes are also a good example of how calling Java classes inside a JavaFX code.

package gravatarexample;
 
import java.security.MessageDigest;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
 
public class MD5 {
   public static String toHex(String message) {
      try {
         MessageDigest md = MessageDigest.getInstance("MD5");
         byte array[] = md.digest(message.getBytes("CP1252"));
         StringBuffer sb = new StringBuffer();
         for (int i = 0; i &lt; array.length; ++i) {
            sb.append(Integer.toHexString((array[i]&amp;0xFF)|0x100).substring(1, 3));
         }
         return sb.toString();
      } catch (NoSuchAlgorithmException e) {
      } catch (UnsupportedEncodingException e) {
      }
      return null;
   }
}

As a Java class in the same package, any JavaFX (or Java) code can call it without any problem. Just to keep the code more clear I’m importing it explicitly. Is this example I also create some Swing interface to give user the option to put his mail, adjust the image size and get a output direct link or html image tag.

package gravatarexample;
 
import gravatarexample.MD5;
import javafx.ext.swing.SwingButton;
import javafx.ext.swing.SwingSlider;
import javafx.ext.swing.SwingTextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.scene.Scene;
import javafx.stage.Stage;
 
var mail = "Email";
var key = "";
 
function gravatalize(mail:String, size: Integer): String {
   return "http://www.gravatar.com/avatar/{MD5.toHex(mail)}?s={size}"
}
 
var inputtxt = SwingTextField {
   columns: 20
   text: mail
}
 
var slider = SwingSlider {
   minimum: 10
   maximum: 128
   value: 100
   vertical: false
}
 
var button = SwingButton {
   text: "Get Gravatar"
   action: function() {
      key = gravatalize(inputtxt.text, slider.value);
      directoutput.text = key;
      htmloutput.text = "<img src="{key}" alt="\&quot;gravatar\&quot;" />";
      photo.image = Image {
         backgroundLoading: true,
         url: key};
   }
}
 
var photo:ImageView = ImageView {
   image: null
}
 
var directoutput = SwingTextField {
   columns: 20
   text: "direct link image"
 
}
 
var htmloutput = SwingTextField {
   columns: 20
   text: "html tag image"
}
 
Stage {
   title: "Gravatar"
   width: 300
   height: 340
   scene: Scene {
      content: [
         VBox {
            spacing: 10
            content: [inputtxt, slider, button, directoutput, htmloutput, photo]
         },
      ]
   }
}

The string itself is assembled in the gravatalize function. You give a mail and it’s returns a Gravatar direct link to the image. There’s many cool ways to use together Gravatar and a JavaFX Internet application.