July 05, 2009

Leveraging JFXtras and Freebase with JavaFX to Create BandmatesFX

Long-time readers of this blog will remember some JavaFX examples in which I query the Freebase.com database, which holds structured information on just about any topic.  Today's post uses JavaFX, with some help from the JFXtras open source project, to query the Freebase database for groups that an artist has played with, and for the artists that have played in those groups.  For example, the screenshot of the BandmatesFX app below shows the results of querying this info on Eric Clapton:

BandmatesFX_clapton
 

To indicate which artist you'd like to query, type the Freebase ID (which as shown above is usually their Wikipedia ID with "/en/" appended to the beginning).  Pressing the Enter key or clicking the Search button initiates the search, which sends a query articulated in the JSON-based Metaweb Query Language (MQL)  The left column of the grid shows the groups that Clapton has played in, and the other images in each row are the artists that have played with that row's group.  Hovering over an image of a band or artist causes the name (in this case Steve Winwood) to appear at the top of the app.

Clicking on an artist performs the same behavior described above on the chosen artist, resulting in the following screenshot that shows bands and artists that Winwood has played with.

BandmatesFX_winwood

Clicking Dave Mason (who was a bandmate with Steve Winwood in Traffic) as shown above will produce the bands and artists with which he has played, ad infinitum.

One of the key enablers of this application is the JSONHandler class (developed by Jim Clarke) found in the JFXtras project.  Take a look at the following listing of the main script in this application to see how it is used.

/*
* BandmatesMain.fx
*
* Uses Freebase and JFXtras with JavaFX to explore connections
* between musical artists
*
* Developed by James L. Weaver to demonstrate using JavaFX and JFXtras
*/

package javafxpert;

import javafx.io.http.HttpRequest;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextBox;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.*;
import javafx.stage.Stage;

import org.jfxtras.data.pull.*;
import org.jfxtras.scene.layout.*;

/**
* Artist for which we're searching bandmates
*/
var artistToSearch:String = "/en/eric_clapton";

/**
* Hover text that contains the name of the artist or group
*/
var nameHoverText:String;

/**
* A reference to the HTTP request, for the purpose of monitoring progress
*/
var req:HttpRequest;

/**
* The root class that will hold the object graph from the JSON results
*/
var freebaseResult:FreebaseResult;

/**
* The base URL for the freebase query
*/
def freebaseURL = "http://www.freebase.com/api/service/mqlread?";

/**
* The base URL for a freebase image
*/
def freebaseImageURL = "http://img.freebase.com/api/trans/image_thumb";

/**
* Create the Freebase query and invoke the JSON handler
*/
function obtainGroupsForArtist(artistFreebaseId:String) {
  artistToSearch = artistFreebaseId;
  var queryUrl = "{freebaseURL}query=\{\"query\":"
    " \{ "
    "   \"/common/topic/image\": [\{ "
    "     \"id\": null "
    "   \}], "
    "   \"/music/group_member/membership\": [\{ "
    "     \"group\": \{ "
    "       \"name\": null, "
    "       \"id\":   null, "
    "       \"/common/topic/image\": [\{ "
    "         \"id\": null "
    "       \}], "
    "       \"/music/musical_group/member\": [\{ "
    "         \"member\": \{ "
    "           \"name\": null, "
    "           \"id\":   null, "
    "           \"/common/topic/image\": [\{ "
    "             \"id\": null "
    "           \}] "
    "         \} "
    "       \}] "
    "     \} "
    "   \}], "
    "   \"id\":   \"{artistFreebaseId}\", "
    "   \"name\": null, "
    "   \"type\": \"/music/artist\" "
    " \} \}";

  println("queryUrl:{queryUrl}");
  var albumHandler:JSONHandler = JSONHandler {
    rootClass: "javafxpert.FreebaseResult"
    onDone: function(obj, isSequence): Void {
      freebaseResult = obj as FreebaseResult;
      println("# of bands:{sizeof freebaseResult.result.musicGroupMemberMembership}");
      req.stop();
    }
  };
  req = HttpRequest {
    location: queryUrl
    onInput: function(is: java.io.InputStream) {
      albumHandler.parse(is);
    }
  };
  req.start();
}

Stage {
  title: "BandmatesFX"
  scene: Scene {
    width: 1000
    height: 750
    content: [
      VBox {
        layoutX: 10
        layoutY: 10
        spacing: 10
        content: [
          HBox {
            spacing: 10
            content: [
              ImageView {
                image: bind Image {
                  url: "{freebaseImageURL}{artistToSearch}?maxheight=80"
                }
              },
              TextBox {
                text: bind artistToSearch with inverse
                columns: 20
                font: Font.font("arial", 14)
                action:function():Void {
                  obtainGroupsForArtist(artistToSearch);
                }
              },
              Button {
                text: "Search"
                strong: true
                action:function():Void {
                  obtainGroupsForArtist(artistToSearch);
                }
              },
              ProgressIndicator {
                progress: bind req.progress
              },
              Label {
                text: bind nameHoverText
                font: Font.font("arial", FontWeight.BOLD, 18)
              }
            ]
          },
          Grid {
            rows: bind for (grp in freebaseResult.result.musicGroupMemberMembership)
              Row {
                cells: [
                  ImageView {
                    image: Image {
                      url: "{freebaseImageURL}{grp.group.id}?maxheight=80"
                    }
                    onMouseEntered:function(me:MouseEvent):Void {
                      nameHoverText = grp.group.name;
                    }
                    onMouseExited:function(me:MouseEvent):Void {
                      nameHoverText = "";
                    }
                  },
                  for (mmbr in freebaseResult.result.
                               musicGroupMemberMembership[indexof grp].
                               group.musicMusicalGroupMember)
                    ImageView {
                      image: Image {
                        url: "{freebaseImageURL}{mmbr.member.id}?maxheight=80"
                        backgroundLoading: true
                      }
                      onMousePressed:function(me:MouseEvent):Void {
                        artistToSearch = mmbr.member.id;
                        obtainGroupsForArtist(mmbr.member.id);
                      }
                      onMouseEntered:function(me:MouseEvent):Void {
                        nameHoverText = mmbr.member.name;
                      }
                      onMouseExited:function(me:MouseEvent):Void {
                        nameHoverText = "";
                      }
                    }
                ]
              }
          }
        ]
      }
    ]
  }
}

As you can see in the listing above, we construct an MQL query that will return information about the bands, and the artists that have played in those bands.  We then supply the JSONHandler with a rootClass, an instance of which will be created and populated with a graph of objects that represents the JSON stream returned from the Freebase server.  JSONHandler uses JavaFX reflection to create instances of classes that correspond to each element name, shown below:

package javafxpert;
public class FreebaseResult {
    public var code: String;
    public var result: Result;
    public var status: String;
    public var transactionId: String;
}


package javafxpert;
public class Result {
    public var commonTopicImage: ArtistImage[] ;
    public var musicGroupMemberMembership: MusicGroupMemberMembership[];
    public var id: String;
    public var name: String;
    public var type: String;
}


package javafxpert;
public class ArtistImage {
    public var id: String;
}


package javafxpert;
public class MusicGroupMemberMembership {
    public var group: Group;
}


package javafxpert;
public class Group {
    public var commonTopicImage: ArtistImage[] ;
    public var musicMusicalGroupMember: MusicMusicalGroupMember[];
    public var name: String on replace {
      name = name.replaceAll("&", "&");
    };
    public var id: String;
}


package javafxpert;
public class MusicMusicalGroupMember {
    public var member: Member;
}


package javafxpert;
public class Member {
    public var commonTopicImage: ArtistImage[] ;
    public var name: String on replace {
      name = name.replaceAll("&", "&");
    };
    public var id: String;
}


As you can see, JSONHandler makes quick work out of populating object graphs from JSON streams, doing the heavy lifting for you.

Another facility of the JFXtras project that we're using is the Grid layout container, as shown previously in the BandmatesMain.fx code listing above.  While you're looking at that listing, notice how easy it is in JavaFX 1.2 to create a ProgressIndicator that reflects the progress of a task such as  HttpRequest.

To get the most out of this post, please build and run this application, putting the JFXtras JAR file (that you can get from the JFXtras Core open source project) on the classpath.  If you'd like a Java Web Start link, please leave a comment.  Also, this is the first cut of the BandmatesFX app, so please leave a comment with ideas for additional features.  And if you possess the graphics design gene (as I admittedly don't), I'd be honored if you'd create a mock-up to make this app look graphically pleasing.

Regards,

Jim Weaver

June 24, 2009

Asynchronicity in JavaFX 1.2

200px-Police-album-synchronicity The asynchronous task model has been much improved in JavaFX 1.2.  Not only does it have a simple and elegant API, but several of the asynchronous tasks (e.g. HttpRequest) in the JavaFX API now use this model.  In addition, there are a couple of progress UI controls introduced in JavaFX 1.2, and they work well with the new asynchronous model.

The JavaFX package that contains the asynchronous-related classes is javafx.async, and a good class to take a look at first is JavaTaskBase.  This class enables you to start a task, check on its progress, and be notified when the task has completed.  JavaFX is single threaded, so the task that is started is one that you define in a Java class (that implements the javafx.async.RunnableFuture interface).  The Java class can then call functions of your JavaFX classes, demonstrating bi-directional integration between JavaFX and Java.

Take a look at the screenshot of a simple example on which Stephen Chin and I collaborated, that demonstrates the capabilities just described:

Async_progressbar

Clicking on the Start the Task button starts a new task and adds a ProgressBar into the scene (up to a maximum of eight, the built-in limit on the number of tasks in JavaFX that can be run in parallel).  When a task completes, its ProgressBar is removed from the scene.  Take a look at the AsyncProgressMain.fx script below to understand how the UI is drawn, and how the tasks are started:

package projavafx.asyncprogress.ui;

import projavafx.asyncprogress.model.*;

import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

var vbox:VBox;

function startTask() {
  def progressBar:ProgressIndicator = ProgressBar {
    progress: bind taskController.floatProgress
  }

  def taskController:TaskController = TaskController {
    maxProg: 100
    onStart:function():Void {
      insert progressBar into vbox.content;
    }
    onDone:function():Void {
      delete progressBar from vbox.content;
    }
  }
  taskController.start();
}

Stage {
  title: "Async and Progress Example"
  scene: Scene {
    width: 200
    height: 250
    content: vbox = VBox {
      layoutX: 10
      layoutY: 10
      spacing: 10
      content: [
        Button {
          text: "Start the task"
          action: function():Void {
            println("Starting TaskController");
            startTask();
          }
        }
      ]
    }
  }
}


Now take a look at the TaskController class that is instantiated in the script above when the button is clicked:

package projavafx.asyncprogress.model;

import projavafx.asyncprogress.model.Ticker;
import javafx.async.RunnableFuture;
import javafx.async.JavaTaskBase;

public class TaskController extends JavaTaskBase, TickerHandler {
  public var maxProg:Integer;
  public-read protected var floatProgress:Number;

  override public function create():RunnableFuture {
    maxProgress = maxProg;
    return new Ticker(this);
  }

  override public function onTick(tickNum:Integer):Void {
    progress = tickNum;
    floatProgress = percentDone / 100.0;
  }
}

Note that the TaskController class above extends the JavaTaskBase class mentioned earlier.  We'll use its capabilities to start and monitor the task.  When the create function of the TaskController instance is called by the JavaFX runtime (as a result of its start function being called) it creates a new instance of the Ticker class that we developed in Java.  As shown in the code below, the Ticker class implements the RunnableFuture interface mentioned earlier.

package projavafx.asyncprogress.model;

import com.sun.javafx.functions.Function0;
import javafx.lang.FX;
import javafx.async.RunnableFuture;

public class Ticker implements RunnableFuture {
  TickerHandler tickerHandler;

  public Ticker (TickerHandler tickerHandler) {
    this.tickerHandler = tickerHandler;
  }

  @Override public void run() {
    for (int i = 1; i <= 100; i++) {
      if (tickerHandler != null) {
        final int tick = i;
        FX.deferAction(new Function0<Void>() {

           @Override public Void invoke() {
             tickerHandler.onTick(tick);
             return null;
           }
        });
      }
      try {
        Thread.sleep(200);
      }
      catch (InterruptedException te) {}
    }
    System.out.println("Ticker#run is finished");
  }
}


The Ticker class shown above counts to 100, sleeping for a couple hundred milliseconds each iteration.  During each iteration it calls the onTick function of the TaskController class shown previously, which implements the TickerHandler interface.  Here's the code for that interface:

package projavafx.asyncprogress.model;

public interface TickerHandler {
  void onTick(int tickNum);
}


For an excellent explanation (including UML sequence diagrams) of asynchronous tasks in JavaFX, see Baechul's JavaFX 1.2 Async blog post.  Also take a look at the Richard Bair and Jasper Potts fxexperience.com post on the subject.

For those interested in JavaFX Mobile, here's a short video clip of this example running on an HTC Diamond phone.  You may want to mute the audio, as I didn't mute the microphone when creating this video. ;-)

Async_progressbar_mobile

As I mentioned in the dynamic Timeline values post, I'm trying to encourage you to compile and run the examples in this blog.  However, please leave a comment if you'd like a Java Web Start link. 

Regards,

Jim Weaver

June 22, 2009

Animating with Dynamic Timeline Values in JavaFX ...and a Scientific Fish Story from 1901

ScientificFishStory A scientific fish story, published in 1901, reports that pike fish living in a tank were separated from minnows by a glass plate.  After a while "a strike at the minnow had come to mean a bump on the nose... Instead of imputing their inability to the glass partition, they considered it some new and remarkable property of the minnows themselves."  Consequently the pike stopped trying to strike the minnows, even after the partition was removed.

I first heard that story when a speaker was illustrating the idea that we often get used to "the way things are", and consequently quit pursuing our passions and dreams.  But this isn't a motivational blog, so I'll stop the inspirational stuff right here and tie the fish story in with the subject of today's post :-)

If you've been developing in JavaFX for a while, you may have gotten used to the idea that dynamically changing values in Timeline key frames don't work as expected.  I was in the same boat (tank?), and instead used the action event handler of a KeyFrame when this kind of dynamic capability was required.  I was pleased to find out recently that this is no longer the case, by virtue of JIRA issue RT-2985 being addressed.

As shown in the screenshot below, I've modified the Metronome example to demonstrate this capability:

MetronomeDynVals

Taking a look at the code below, notice that clicking anywhere in the scene causes the values in the second KeyFrame of the Timeline to be assigned the coordinates of the mouse click.  The net effect is that one end of the blue line (which is bound to the variables that are interpolated by the timeline) move to where you clicked the mouse.  Here's the code listing for this example:

/*
* MetronomeDynVals.fx - A simple example of animation using a Timeline
* with dynamic KeyFrame time and values.
*
* Developed 2009 by James L. Weaver jim.weaver [at] javafxpert.com
* as a JavaFX Script SDK 1.2 example
*/
package projavafx.metronome1.ui;

import javafx.animation.KeyFrame;
import javafx.animation.Interpolator;
import javafx.animation.Timeline;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Slider;
import javafx.scene.input.MouseEvent;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

var durMs:Number = 1000;
var xVal:Number = 100;
var yVal:Number = 50;
var endXVal:Number = 300;
var endYVal:Number = 50;
var anim = Timeline {
  keyFrames: [
    KeyFrame {
      time: 0ms
      values: [
        xVal => 100,
        yVal => 50
      ]
    },
    KeyFrame {
      time: bind 2000ms - (durMs * 1ms)
      values: [
        xVal => endXVal tween Interpolator.LINEAR,
        yVal => endYVal tween Interpolator.LINEAR
      ]
    },
    KeyFrame {
      time: bind (2000ms - (durMs * 1ms))*2
      values: [
        xVal => 100,
        yVal => 50
      ]
    }
  ]
  repeatCount: Timeline.INDEFINITE
};

Stage {
  title: "Metronome Dynamic Values"
  visible: true
  scene: Scene {
    width: 400
    height: 500
    content: [
      Rectangle {
        width: 400
        height: 500
        fill: Color.TRANSPARENT
        onMousePressed: function(me:MouseEvent):Void {
          endXVal = me.x;
          endYVal = me.y;
        }
      },
      Line {
        startX: bind xVal
        startY: bind yVal
        endX: 200
        endY: 400
        strokeWidth: 4
        stroke: Color.BLUE
      },
      HBox {
        layoutX: 60
        layoutY: 420
        spacing: 10
        blocksMouse: true
        content: [
          Button {
            text: "Start"
            disable: bind anim.running
            action: function():Void {
              anim.playFromStart();
            }
          },
          Button {
            text: "Stop"
            disable: bind not anim.running
            action: function():Void {
              anim.stop();
            }
          },
          Slider {
            min: 100
            max: 2000
            width: 500
            value: bind durMs with inverse
          },
        ]
      }
    ]
  }
}



Dynamically Altering the time Variable of a KeyFrame

In addition to dynamically changing the values of a KeyFrame, you can also alter the value of its time variable.  To demonstrate this, the value of the Slider is bi-directionally bound to a variable from which the time value of the second KeyFrame is calculated.  Consequently, moving the slider changes the speed of the animation.

By the way, I didn't supply a Web Start link, because I'd like to encourage you to compile and run the application.  If you'd like a Web Start link, please leave a comment.

Regards,

Jim Weaver

P.S. Thanks to Eric M. Smith (who *does* have a motivational blog) for adding a third KeyFrame to this example (see his comment to this post).  This addition makes the behavior more metronome-like, and if you click in the lower-right area the pendulum exhibits some John Travolta/Saturday Night Fever dance-action :-)

June 19, 2009

Create a News Ticker with JavaFX 1.2 RssTask/AtomTask

Stock_ticker JavaFX 1.2 has many new features, not the least of which is a stone-simple way of reading RSS and Atom feeds.  The new classes that contain much of this functionality are javafx.data.feed.rss.RssTask and javafx.data.feed.atom.AtomTask, respectively.

Take a look at this post by Rakesh Menon that shows you how to create news tickers with these classes.

Also, I'll give a free copy of the Pro JavaFX early access eBook (rewritten for 1.2) to the first person that leaves a comment with the name of the inventor of the Stock Ticker shown in the image above. :-)

Update: We have two winners of the Pro JavaFX early access eBook: Steve Sobczak, and Warren Strange (author of the Strange Brew blog).  Steve asserted that Edward A. Calahan invented the stock ticker, and Warren asserted that Thomas Edison did.  I'm giving a book to each of them, citing the following paragraph from The Stock Ticker Company web site:

"Edward A. Calahan invented the first stock ticker, which was introduced to the New York Stock Exchange in 1867. A young Thomas Edison improved on Calahan's design and made the stock ticker easier to use and maintain. It was Edison's first profitable innovation, and it introduced him to the powerful Wall Street businessmen who funded his subsequent inventions such as the phonograph, the light bulb, and motion pictures. It is the Universal Stock Ticker that we have reproduced."

Congratulations Steve and Warren!

Regards,

Jim Weaver

June 17, 2009

Skinning Architecture in JavaFX -- straight from the horse's mouth

Skinlevels No, I'm not calling Richard Bair a horse, but rather using an idiom that has its origins in horse racing.  From The Phrase Finder:

"In horse racing circles tips on which horse is a likely winner circulate amongst punters. The most trusted authorities are considered to be those in closest touch with the recent form of the horse, i.e. stable lads, trainers etc. The notional 'from the horse's mouth' is supposed to indicate one step better than even that inner circle, i.e. the horse itself."

In their latest fxexperience.com blog post, Richard (Jasper is on holiday) sheds a lot of light on the skinning architecture in JavaFX 1.2 and what is planned for the next release.

Regards,

Jim Weaver

June 16, 2009

Painting with JavaJeff (JavaFX Jeff?)

One of the great features of JavaFX is that it can instantiate and call methods of Java classes.  Java author "JavaJeff" Friesen has created a Painter/Canvas infrastructure using JavaFX and Java.  This infrastructure supports complex/fast painting possibilities such as fireworks, plasma, fractals, and even fire.

PlasmaPainter

Check out Jeff's blog post that provides the code, an explanation, and a Web Start link for the "plasma" painting example shown in the screenshot above.

Regards,
Jim Weaver


June 13, 2009

Pro JavaFX Book SDK 1.2 Rewrite Complete

All Pro JavaFX early access eBook chapters have been updated to SDK 1.2.  They are being shipped to the printer, so the book composed of atoms vs. bits will be available soon.

In addition, we're releasing a 16-page Pro JavaFX 1.2 children's book, shown below (not really). :-)

Pro-bunny

The image shown above was created by Stephen Chin for the slides in his presentation with Josh Marinacci on WidgetFX at JavaOne.  The Nabaztag bunny is a robot used in the presentation, but neither rabbits nor robots were harmed in the making of this image or during the presentation :-)  By the way here are the slides for the presentation on JavaFX that Stephen and I gave at JavaOne.

If you're interested in what's between the covers of the book, here's a brief description of each chapter:

  • Chapter 1, Getting a Jump Start in JavaFX, gives you a jump start in developing applications in the JavaFX language, brings you up to date on the brief history of JavaFX, and shows you how to get the JavaFX software development kit. It then walks you through the process of compiling and running JavaFX applications, and teaches you a lot about the JavaFX language and API while walking through example application code.
  • Chapter 2, Taking a Closer Look at the JavaFX Script Language, covers the fundamentals of the JavaFX Script language, including  concepts such as variables, primitive types, literal values, and basic operations.  JavaFX sequences are introduced in this chapter, along with how to access their members and perform sequence comprehension.
  • Chapter 3, Creating a User Interface in JavaFX, associates the metaphor of creating a theatre play with JavaFX development, and discusses creating a stage, a scene, nodes, a model, event handlers, and animating some of the nodes.  It then delves into each of these concepts using JavaFX examples, finishing up with a Pong-like game that demonstrates how to detect when nodes in the scene have collided.
  • Chapter 4, Using Functions, Classes, and Other Advanced Features, discusses how to define functions and classes of your own. It then covers function signatures and function types, and how to write anonymous functions.  From there, this chapter introduces how to define class hierarchies, and the covers the details about class types. It also discusses what happens when an object is instantiated and how you can exert control over the process.
  • Chapter 5, Creating Custom UI Components and Charts in JavaFX, explains how to define custom UI components of two fundamentally different types -- custom nodes, and UI controls.  After showing you how to create custom nodes in the context of creating a couple of color selection components, it covers how to create UI controls in the context of a stoplight control that has multiple skins.  The chapter finishes by teaching you how to use the charting controls to simply and easily create charts in JavaFX.
  • Chapter 6, Using the Media Classes, explores the capabilities of the JavaFX media classes that make it easy for developers to incorporate playback support for most of the popular formats.   This chapter demostrates how simple it is to include basic media playback support in your JavaFX applications and then show you how to build more sophisticated playback applications.
  • Chapter 7, Dynamically Laying Out Nodes in the User Interface, shows how you can leverage the dynamic layouts mechanisms of JavaFX to build complicated user interfaces with zero static positioning.  These mechanisms include the bind statement, powerful custom layouts built on top of the Panel and Container classes, and the built-in layouts including HBox, VBox, Flow, Tile, and Stack.
  • Chapter 8, Extending JavaFX with Third-Party Libraries, introduces several of the JavaFX third-party extensions that simplify the development of applications.   All of the third-party extensions introduced in this chapter are available as free or open source libraries. This ensures that anyone can make use of these libraries, and also guarantees that you will not be locked into a specific vendor.
  • Chapter 9, Building a Professional JavaFX Application, shows you some of the professional techniques we use to write real-world JavaFX applications. You will need them when working with a graphic designer, and you will find them useful when you are confronted with the memory usage and performance trade-offs that developers need to consider for real applications. This chapter also provides tips and techniques for enhancing the user’s experience.
  • Chapter 10, Developing JavaFX Mobile Applications, teaches you the basics of JavaFX Mobile development, which will enable you to write portable applications that work on both desktop and mobile devices.  During this chapter you’ll gain an understanding of the Common Profile, learn how to take advantage of the Java ME capabilities beneath JavaFX Mobile, and adopt JavaFX Mobile best practices that will enable you to write high-performance applications.
  • The Appendix presents the keywords and the operators of JavaFX Script.  Precedence and associativity rules are supplied for the operators.

Regards, and enjoy the book!

Jim Weaver

June 12, 2009

JavaFX Authoring Tool Demo at JavaOne

At JavaOne 2009 during James Gosling's Toy Show, Tor Norbye demonstrated the current state of the long-awaited JavaFX Authoring Tool. 

JavaFXAuthoringTool

Some of the demonstrated features were:

  • The ability to position/orient a node (e.g. an image) in multiple places on the stage, each corresponding with a point in time on a timeline (represented by a slider).  Each point in time becomes a KeyFrame, and interpolations are calculated based upon position/orientation.  Dragging the slider results in seeing the node move and rotate through the positions in which the node was placed.  I assume that scaling and other transforms will be supported in the tool as well.  Tor mentioned that various interpolations are supported (LINEAR, EASEIN, EASEOUT, and EASEBOTH).  I assume that spline interpolation will be supported as well.
  • Placing UI controls on the stage, hooking them up with event handlers, as well as binding to instance variable values (e.g. in other UI controls).
  • Targeting an application at multiple screens (e.g. desktop, mobile phones), with the ability to customize for each screen.

Augusto Sellhorn (AKA sellmic) has compiled some video clips and his thoughts about the JavaFX Authoring Tool in a blog post.  If you didn't see the Toy Show, checking out Augusto's post is a quick way of seeing the preview of the tool.

Update June 13, 2009: Augusto created another blog post with new screenshots, links and thoughts on the JavaFX Authoring Tool.

Regards,

Jim Weaver

June 10, 2009

Dean Iverson is Off Da [JavaFX] Charts!

Pro JavaFX co-author and homie Dean iverson is blogging again, beginning with a series on JavaFX 1.2 Charts

ChartHierarchy

This series is based on charting content that he wrote for the book (in chapter 5), and will help you get up to speed quickly on this new feature of JavaFX.  Check out the first installment, perhaps with a cup of coffee and a piece of π.  (You'll get that pun when you read the article :-)

Congrats Dean, and keep those blog posts rolling!

Regards,
Jim Weaver    

June 08, 2009

Are You Experienced (in JavaFX)? Jasper Potts and Richard Bair are sharing their experience!

Hendrix_AreyouexpUS "If you can just get your mind together
Then come on across to me
We'll hold hands and then we'll watch the sunrise
From the bottom of the sea
But first, are you experienced?
Have you ever been experienced?"

-Jimi Hendrix from "Are You Experienced"

I'm pleased to let you know that Jasper Potts and Richard Bair have started a blog entitled fxexperience.com, in which Jasper and Richard are posting their thoughts, insights, and experiences with JavaFX. These blokes are key members of the JavaFX team at Sun Microsystems, so the info in the blog is "directly from the source". Richard is the API design lead, key developer on the scene graph, and lead of JavaFX UI Controls. Jasper has annoyingly amazing graphical ability, and is the creator of the Charts API in JavaFX.  Join me in subscribing to this incredible blog!

Bair-potts-pie

Regards,
Jim Weaver

My Photo

Upcoming Speaking Engagements:


  • Stephen Chin and Jim Weaver speaking about JavaFX Platform

  • Speaking on JavaFX and Java at Øredev in Malmö, Sweden on 2-6 November, 2009

Upcoming JavaFX Training:


  • Developing Secure, Rich Internet Applications Hosted on a Variety of Clients Using JavaFX Technology

Enter your email address:

Delivered by FeedBurner

Available now as early access eBook


  • Click book image above to obtain eBook

Twitter Updates

    follow me on Twitter

    Affiliations:

    DZone Links:


    July 2009

    Sun Mon Tue Wed Thu Fri Sat
          1 2 3 4
    5 6 7 8 9 10 11
    12 13 14 15 16 17 18
    19 20 21 22 23 24 25
    26 27 28 29 30 31  

    Disclaimer:

    • By reading this site, you are agreeing that under no circumstances will Veriana Networks, Inc. or its affiliates be responsible for (1) any information contained on or omitted from the site, (2) any person's reliance on any such information, whether or not the information is correct, current or complete, (3) the consequences of any action you or any other person takes or fails to take, whether or not based on information provided by or as a result of the use of the sites.