Thứ Ba, 3 tháng 1, 2012

JavaFX 2's Ensemble and other Sample Applications

There are several places within the JavaFX 2 documentation that the sample application Ensemble is referenced. Ensemble is the largest JavaFX sample application provided in the JavaFX 2.0 samples. Acquiring the JavaFX 2 samples, using the JavaFX 2 samples, and learning from the JavaFX 2 samples are the subjects of this post.

The JavaFX Developer Downloads page currently features "JavaFX 2.0.2 General Availability Download" and includes a link for downloading JavaFX Samples [only for "Microsoft Windows (x86 and x64)" as of this writing]. The downloaded file, javafx_samples-2_0_2.zip, is about 18 MB in size. The contents of this ZIP file, when extracted are shown in the next screen snapshot.

Once the samples ZIP has been downloaded and its contents extracted, the Ensemble sample application can be executed. One way to do this is to take advantage of the executable JAR in the main unzipped samples directory as shown in the next screen snapshot (java -jar Ensemble.jar).

The JavaFX 2 Ensemble sample application starts up and appears as shown in the next screen snapshot.

There are numerous items that can be clicked on in the Ensemble application to learn more details about what it is and how it is implemented. For example, clicking on "Adv Candle Stick Chart" opens up the "Custom Candle Stick Chart" as shown in the next screen snapshot.

The above screen snapshot shows Ensemble with the "Sample" tab for this specific example. Clicking on the "Source Code" tab displays the source code for the same sample. As shown in the next screen snapshot, this tab includes a button for copying the JavaFX 2 source code that built that sample.

The combination of the source code with what it produces in the Ensemble sample application can help developers to learn what's available and how to use various parts of JavaFX. Sections currently included in Ensemble include Animation, Charts, Controls, Graphics, Language, Layout, Media, Scene Graph, and Web.

The downloadable JavaFX 2 samples also include Brick Breaker (BrickBreaker.jar) and the next screen snapshot was taken of it in action.

Running the executable JAR SwingInterop.jar demonstrates the "JavaFX 2.0 in Swing" sample application (screen snapshot shown next).

The JavaFX 2 samples ZIP also includes FXML-LoginDemo, which is a simple login sample that includes an FXML file (profile.fxml) in its source. It's shown in the next screen snapshot.

The Ensemble application is by far the largest of the sample applications that are included in the JavaFX 2 samples ZIP file and is the "flagship" sample application. Brick Breaker is relatively large for a single application. All of the samples have value in showing what JavaFX is capable of and in providing source code to demonstrate how to accomplish these very feats with JavaFX.

Thứ Hai, 2 tháng 1, 2012

Scala for 2012? Deciding Whether to Invest In a Programming Language

I have found it both interesting and rewarding to learn a new programming language or major framework on a roughly yearly basis. If forced to self-identify with any single programming language, it would be Java. However, over the years, I've used C and C++ fairly extensively and have used and learned enough to be dangerous about several other languages including shell scripting languages, Perl, JavaScript, Pascal, C#, Ruby, JRuby, Groovy, PHP, and Python. Of the latter group of languages (Ruby, JRuby, Groovy, PHP, and Python), Groovy has had the most practical benefit for me, but I have learned valuable idioms, best practices, and different ways of thinking from using the other languages.

In some years, I've not been as quick to learn a language in a year in which I've been learning either a major framework for that language or in a year in which a language I am familiar with undergoes significant changes. For example, Struts and the Spring Framework dominated my time as I learned each of them. JavaFX has similarly dominated my interest in recent weeks. When not working with a new language, I tend to focus on libraries and frameworks of the languages I am comfortable with. I have spent more time on Guava this year, for example.

Learning a new language does provide many benefits. However, these benefits don't come for free. There is always an opportunity cost associated with learning anything new. If a programming language is particularly different than what one is used to, this opportunity cost can be great. The opportunity cost can be manifest as many different things. It might be lower productivity than could be had using a known language. It might be missing out on learning a new framework, library, or approach in the more familiar language. The opportunity cost might be having to settle on fewer or choosing different features that better fit the new language. The opportunity cost may be as simple as not being able to do other things one would want to do and might have time to do if using a familiar language.

Because there are so many potential opportunity costs associated with learning a new programming language, I try to be careful about which I invest my time in. I typically have a compelling reason for learning a new language. Compelling reasons might include specific advantages of a language (such as PHP for many Web 2.0-centric projects) or widespread use and "employability" of that language. Other reasons might be to learn new techniques that can be adapted to more familiar languages. Perhaps the most compelling reason I've learned a new language has been to read and maintain code or scripts that I have handed to me and am assigned responsibility for.

For several years now, I've been somewhat curious about Scala, but have not yet committed myself to using it and learning it because other languages, frameworks, and tools have grabbed my attention. Typically, I've had some motivation that has made these tools, languages, or frameworks seem most worth my investment of time and energy. For example, the need to have a nice scripting language that meshes well in my Java development environment led me to Groovy. My attendance at JavaOne 2010 and JavaOne 2011, coupled with my interest in a modern GUI technology, has led to my interest in JavaFX. I spent time with Python after being in a position where I needed to read and modify Python scripts.

I recently welcomed the opportunity to pose some questions to Scala creator Martin Odersky related to what is in Scala that might motivate me (and others) to invest time and energy into learning Scala. As I articulated the questions I had for Martin, I realized that these are really the things that I informally look at when investigating a new language. I typically spend an hour to two finding a language's highest-level motivations first and only invest more time in that language if it seems to be a good potential fit for me. Martin has agreed to me posting my questions and his answers and they are shown next (I have added hyperlinks).

Question: What is the most compelling/motivating reason or reasons that one might want to invest time in learning Scala as opposed to continuing use of Java (mostly for applications in my case) + Groovy (mostly for development environment scripting in my case)? For example, Groovy appealed to me at a high level as a way to script with libraries, idioms, and syntax that I was comfortable with from Java application development experience.
There are actually quite a few different facets of Scala that individuals attach to for different reasons. Some are attracted by the succinct syntax and resulting productivity. Others gravitate to the stability of the JVM and runtime performance of a compiled language (versus an interpreted language, like Groovy), or the ability of a sophisticated type system to help programmers avoid errors that would otherwise crop up at runtime. Others find the functional style of programming to be a more natural way to reason about their application logic.

One of the strongest attractors, from a practical point of view, is that Scala (and the rest of the Typesafe Stack -- including Akka and Play) are designed to provide better tools to address the dual challenges of parallel and concurrent programming. With the advent of mainstream multicore/manycore hardware, and the increasing scale of applications that developers are charged to build, many industry developers are looking for higher level abstractions than threads and locks for building at this next scale. Many find that the functional style, immutable state, actor concurrency model, and other concepts at the heart of Scala make it simpler to build parallel and concurrent applications.

Question: What are Scala's biggest strengths, advantages, and innovative features?
At a high level, Scala seeks to be a pragmatic language that scales from the smallest scripts to the largest distributed systems.

One major thread of innovation in Scala is its unique blend of object-oriented Java with functional programming concepts. Scala's libraries build on this foundation to provide outstanding support for concurrency and parallelism, for example through the actor programming model and the built-in parallel collections introduced in Scala 2.9.

Scala's expressive type system and syntax helps developers build more reliable code and greatly increase extensibility, especially for library developers and those building domain-specific languages (DSLs).

Finally, it's important not to overlook the fact that Scala is deeply integrated with Java, supporting blended Scala/Java projects and allowing developers to apply their skills and investments in Java immediately when they start working with Scala.

Question: What are Scala's biggest weaknesses, disadvantages, and plans for improvement?
One of the challenges for a relatively young language like Scala is the maturity of tools. In particular, the Scala IDE for Eclipse has had its rough edges in the past -- one of the reasons that Typesafe, as the leading commercial contributor to Scala, has invested substantial resources in overhauling the IDE with version 2.0 (just released in December 2011).

Another challenge for adoption is that Scala does introduce with functional programming a new mode of thinking about programs, which takes some time to learn. It makes the transition gentle, because one can start writing Scala code like more concise Java code. But as Scala's native library ecosystem grows chances are that newcomers to the language will come across to some of its more foreign features before they have developed a good understanding. To avoid culture shock, we need to develop a set of best practices and good tutorials that help the transition. "Programming in Scala", which I have co-authored, is a comprehensive tutorial of the object/functional style. Cay Horstmann's "Scala for the Impatient", available as a free preview on the Typesafe site, is a pragmatic, fast-paced introduction.

Question: What situations/scenarios/use cases is Scala best and worst suited for?
As described above, Scala and its frameworks like Akka and Play really shine for building systems that need to scale on multiple fronts -- across cores, across machines in a cloud environment, and across large software teams.

Traditionally, one area where Scala or other JVM-hosted languages would not be considered well suited would be lower-level systems programming. But interestingly, we see evidence of forward-looking systems developers increasingly embracing managed runtime languages like Scala because they face fundamental challenges in building reliable systems for the era of multicore hardware and distributed deployments.

Martin's responses validate some of my own conclusions about Scala from reading posts by Scala enthusiasts and even some of the detractors. In terms of motivation, I have a difficult time believing that learning Scala primarily as a scripting language will be very motivating because I'm pretty happy with Groovy for scripting. However, for development of applications, I tend to use Java and not Groovy and I wonder if it's in that area where I'd be most likely to benefit from learning and using Scala.

Once I determine that a language is worth investing in, the next step is deciding how to best learn it. Reading about it is a necessity, but using it is what really helps me learn it and also what helps me identify the things I don't like about it. The trick is to come up with a somewhat realistic example that is easy enough to implement, but interesting enough to prove out some concepts. A "Hello World" is okay to get one's feet wet, but doesn't really test how the language fares for a developer's specific needs. My favorite initial examples are ones that actually provide benefit in addition to being a mechanism for learning. For example, when I was learning Groovy, I developed several scripts early on that were helpful to me as scripts in their own right regardless of the language they were written in. In those cases, I gained familiarity with Groovy while also receiving other utilitarian benefits.

The JavaWorld article Learn Scala with Specs2 Spring describes how a Java developer who uses the Spring Framework can use the author's company's Specs2 Spring for integration testing and also benefit from "an efficient and safe way to learn the patterns of object-functional programming with Scala." The entire premise of this article is exactly the kind of thing I like to do when learning a new language: combine legitimate benefit with learning of the new language.

One other thing to think about when trying out a new language is to ensure that one is trying it out for the correct situations. This was easy for me with Groovy: I tried out Groovy first in situations in which I wanted the power of the JVM or the scope of the JDK, but wanted a scripting-friendly language. A developer can quickly decide a language is "not good" simply because the situation in which the language used is not a great fit for that language. Related to this, another issue I try to keep in mind when learning a new language is that it's not fair to compare a language I know well and have spent thousands of hours with to a language that I've spent a few hours with. Unless I encounter some real deal-breakers early in the process, I try to not let "little problems" or things I don't like about the new language prevent me from giving it a real chance. An excellent recent post on this is Rob Pike's Esmerelda's Imagination. All that being stated, there are times I run into a true deal-breaker that makes me realize I should not invest any more time in a particular language because it doesn't fit my needs. That doesn't necessarily mean there's anything wrong with the language, but simply that it doesn't fit my needs well. An example of this would be using Java for a real-time system in Java's early days.

I think I'm almost ready to commit to spending more time with Scala. I'm not the type to make new-year resolutions, but it just so happens that it seems like the right time to give Scala a closer look. If I really do start to invest more time in Scala, my plan is to first re-read Bruce Eckel's Scala: The Static Language that Feels Dynamic and then read the A1 chapters of Scala for the Impatient, trying out and adapting examples. If I'm still interested in Scala after that, I can invest more at that time.

Do I still have reservations about spending time on Scala? Of course. One of my biggest concerns is best articulated by someone who actually seems to have tried out Scala. Cédric Beust states, "In my experience with Scala, it's hard not to like the language in the first week and it's hard to still be in love with it after reading the 700+ pages of a book about it." On the other hand, Casper Bang articulates well why I think I maybe I should spend time with Scala despite any other obvious motivations: "So I guess my point is, even if I do find Scala hyperbolish and biting over a bit too much; the majority of identifiable alpha-geeks that I track, are moving this way and as a practicing professional, I can not afford to ignore this."

The post Offbeat: Scala by the end of 2011 – No Drama but Frustration is Growing and the feedback comments related to that post are insightful and seem to reiterate some of the issues that Martin pointed out that Scala must deal with. In particular, when I look at the issue most likely to deter me from spending time on Scala, it is the risk that Scala may never take hold in mainstream development. If that turns out to be the case, then the primary advantage of learning Scala would be to change my way of thinking about things and that's not always necessarily worth the opportunity cost and other costs. This post and the feedback comments contain multiple sides of the same issue and are another reminder that I probably need to do more with Scala to decide for myself how I feel about it.

My plan as of right now is to invest significant time and effort into learning basics of Scala and applying it to some "realistic" examples. I even have plans to blog on what I learn. But, I have had these types of plans before and been distracted by some other shiny thing that has come my way. I think this time will be different, but I should know for certain by the end of 2012.

Applying Sepia Effect to Loaded Images in JavaFX 2.0

In this blog post, I look at a very simple JavaFX 2.0 application that loads an image provided on the command-line and presents it in both normal form and with JavaFX 2.0's SepiaTone effect applied to it. The simple application presents the two images side-by-side for dramatic effect. To accomplish this, the simple example demonstrates loading images in JavaFX based on a URL, use of the HBox layout component, and accessing command-line parameters in a JavaFX application using Application's getParameters() method.

In general photography, use of sepia can make a photograph appear older or like an antique. The JavaFX SepiaTone Effect accomplishes this for JavaFX components, including loaded images. The following code snippet shows how this can be accomplished.

SepiaEffect.java

package dustin.examples;

import java.util.List;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.effect.SepiaTone;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

/**
* Simple demonstration of the SepiaTone Effect.
*
* @author Dustin
*/
public class SepiaEffect extends Application
{
/** Default width of displayed photographs/images. */
private final static int DEFAULT_WIDTH = 540;

/**
* Overridden (from parent Application class) method.
*
* @param stage Primary stage.
* @throws Exception JavaFX 2.0 application exception or file I/O exception.
*/
@Override
public void start(final Stage stage) throws Exception
{
// Get command-line parameters and access first argument as image URL.
final Parameters params = getParameters();
final List<String> parameters = params.getRaw();
final String imageUrl = !parameters.isEmpty() ? parameters.get(0) : "";

// The third-to-last 'true' preserves height/width ratio and the next
// 'true' argument indicates better quality (smooth) filtering should be
// used and the final 'true' indicates that background loading should be
// used. The imageUrl must really be a URL and begin with a protocol
// such as file:\\ or http:\\.
final Image loadedImage = new Image(imageUrl, DEFAULT_WIDTH, 405, true, true, true);
final ImageView originalView = new ImageView(loadedImage);
final ImageView sepiaView = new ImageView(loadedImage);
sepiaView.setEffect(new SepiaTone()); // default is full (1.0) effect

final HBox horizontalBox = new HBox();
horizontalBox.getChildren().add(originalView);
horizontalBox.getChildren().add(sepiaView);

stage.setTitle("Demonstration of JavaFX 2.0 Sepia Effect");
final Group rootGroup = new Group();
final Scene scene = new Scene(rootGroup, DEFAULT_WIDTH*2, 405, Color.WHITE);
rootGroup.getChildren().add(horizontalBox);
stage.setScene(scene);
stage.show();
}

/**
* Main function for running demonstration of JavaFX 2.0 SepiaTone Effect.
*
* @param arguments Command-line arguments: none expected.
*/
public static void main(final String[] arguments)
{
Application.launch(arguments);
}
}

The above example uses fewer than 70 lines, including white space and overly verbose comments in code intended for a blog post example. When run against a photograph I took in Juneau, the application looks like that shown in the next screen snapshot.

The source image was only loaded once into a single Image instance, but two different ImageView instances were used to present that single Image instance both in its original color scheme and with the sepia effect. The application of the sepia effect is only a single line. The level of "sepia-ness" can be specified, but I used the default in this case. The HBox layout component made it easy to place the images side-by-side.

As a comment in the code sample indicates, the String provided to the Image constructor needs to be a URL that includes a protocol such as http or file. For example, in my case the string I provided as the command-line argument to the sample application was "file:///C:/Users/Dustin/Pictures/P1010804-juneau.jpg". Without the "file://" prefix, the application is not able to find the image to load it.

This blog post has shown that loading images in JavaFX 2.0 and applying effects to them is straightforward.

Thứ Bảy, 31 tháng 12, 2011

The Challenges of a JavaFX Reboot

In Jonathan Giles's post An FX Experience Retrospective, he starts by looking at the history of JavaFX and focuses on "what has happened in the world of JavaFX" in 2011. I was highly skeptical of JavaFX prior to JavaOne 2010 (see here and here for examples), but started to think more positively about it after the JavaOne 2010 and JavaOne 2011 announcements related to JavaFX. One thing that has been a little tricky about learning JavaFX since JavaOne 2011's big announcements has been knowing for certain whether a particular resource on JavaFX applies to JavaFX 1.x or JavaFX 2.x. Reading the An FX Experience Retrospective post provided a different perspective on the risks and challenges Oracle and the JavaFX team has faced in making this major overhaul.

Giles writes in his post, "Another vivid recollection I have from JavaOne 2010 is the various reactions that people had of this news. It varied from those in shock at losing their favourite language, to those who said it was long overdue and was the right way to proceed with JavaFX." I was in the latter group, welcoming this change and I would have liked to see it happen even sooner. The ability to use JavaFX with standard Java language and APIs was a huge benefit in my opinion and finally gave credence to the pro-JavaFX argument to Java developers that "JavaFX is Java." The JavaOne 2011 announcements of making JavaFX open source and making it part of standard Java SE were likely less controversial for Java developers (who wouldn't want these characteristics?) and are also important to me in my renewed interest in JavaFX.

For developers just learning JavaFX, it can be a bit tricky to know if an online resource is for JavaFX 1.x or 2.x without delving into the article. The changes in JavaFX from 1.x to 2.x are significant enough that I generally don't want to risk confusion by reading JavaFX 1.x resources (though some have found value in reading JavaFX 1.x resources in preparation for using JavaFX 2.0). However, there are some clues that can help make it quicker and easier to identify which version of JavaFX is applicable.

It is most obvious that an article is about JavaFX 2.0 when it explicitly states so. I try to do this with my blog posts on JavaFX 2.0, though I'm sure I occasionally forget to do so. When an article or blog post does not state the version of JavaFX specifically, another good clue is the date of the resource. In general, it is usually safe to assume that anything written about JavaFX before late 2010 is about JavaFX 1.x and it is similarly safe to assume that most things written about JavaFX in 2011 or later are about JavaFX 2.x.

Another clue to watch for is discussion in a resource that includes JavaFX Script or FXML references. The former (JavaFX Script) was exclusive to JavaFX 1.x and the latter (FXML) is exclusive to JavaFX 2.x.

Some really good documentation on JavaFX 2.x has been made available recently. The JavaFX 2.0 documentation states the following about JavaFX 2.0 versus JavaFX 1.3:

JavaFX 2.0 is the latest major update release for JavaFX. Many of the new features introduced in JavaFX 2.0 are incompatible with JavaFX 1.3. If you are developing a new application in JavaFX, it is recommended that you start with JavaFX 2.0.

The JavaFX 2.0 documentation contains many newly written or updated articles and posts on JavaFX 2.0. This set of documentation includes What is JavaFX?, Getting Started with JavaFX, Working with the JavaFX Scene Graph, Introduction to FXML, Getting Started with FXML, and Using JavaFX Charts.

Books on JavaFX provide another perspective on the challenges associated with the major shift in JavaFX's vision. Most JavaFX books that are currently available were written for JavaFX 1.x. berry120 (who has also blogged on JavaFX 2) recently asked, Any decent books on JavaFX 2? As far as I can tell, the only JavaFX 2.x book currently available is Carl Dea's JavaFX 2.0: Introduction by Example (I hope to write a review of this short, recipe-oriented book in the near future). This book has a publication date (2011) and JavaFX 2.0 in its title, making it clear that it's on Java FX 2.0. With books, which typically have longer time between writing and publishing, even early 2011 publications dates might still mean a book on JavaFX 1.x. Another good clue with books is the price of used books in the Amazon Marketplace. Books on old and/or deprecated language versions tend to be very cheap.

Other books on JavaFX 2.0 are likely to come. Pro JavaFXTM 2 Platform A Definitive Guide to Script, Desktop and Mobile RIA with JavaTM Technology has an advertised publication date of 12 February 2012.

Even downloading the appropriate version of JavaFX might be a tad tricky if one doesn't pay attention. As of this writing, the link http://javafx.com/downloads/windows.jsp provides download links for JavaFX 1.x. This is indicated in the next screen snapshot. The correct location for downloading JavaFX 2.x is the the JavaFX Developer Downloads at http://www.oracle.com/technetwork/java/javafx/downloads/index.html. Depending on what one searches for in a search engine such as Google's search engine, either can be the first returned result.

Carefully wading through online resources and selecting books to purchase is tricky for developers because of the major shift in JavaFX's long-term vision. Giles's post provides some insight into the even greater effort required within Oracle and the JavaFX team to make this major shift. As painful as the shift is, I believe this shift in vision coming at the cost of short-term pain provides JavaFX a fighting chance for a prosperous long-term future.

My Most Popular 2011 Blog Posts

In this post, I briefly summarize my "eight" most popular "2011" posts (six actually posted in 2011 and two posted in late 2010). The two common themes of these posts seem to be broad applicability and future focus. I expected a few of these posts to do well and was surprised that some of these did as well as they did (and surprised that some others did not make the list).

8. All I Want for Java 8 Is... (27 April 2011)

The popularity of the post All I Want for Java 8 Is... is probably best explained by its focus on what may come in a future version of Java. Having DZone (a "Big Link"), reddit, and JavaWorld references also certainly helps.

[7.] Ten Tips for Using Java Stack Traces (22 October 2010)

I personally like the post Ten Tips for Using Java Stack Traces because I believe it is one of those posts that can be useful to people who are relatively new to Java and provides fairly comprehensive coverage and tips for these new Java developers in a very specific but common area. When I wrote that more developers should write blog posts, I had blogs like this one in mind.

6. Java State of the Union: One Year Under Oracle (12 February 2011)

This may be the most surprising post (to me) to have fared so well in 2011.

The post Java State of the Union: One Year Under Oracle turned out to be especially interesting to me now from a historical perspective. At the time of that writing, the future of Java was near a low point (perhaps back a little higher than its lowest point thanks to the already announced participation of IBM and Apple in OpenJDK). It's difficult to believe how much things have changed in the same year! At the time of the writing of my sixth most popular post of 2011, the focus was on issues with the Java Community Process (JCP) and talk of forking Java. Oracle, to their credit, seems to have had a handle on what was happening at this time and, by JavaOne 2011, had made some significant changes that changed the overall Java community outlook for the better. 2011 was a great year for Java, but we didn't necessarily have any reason to believe that would be the case in mid-February of this year.

5. JavaOne 2011: The Definitive Set of HotSpot Performance Command-line Options (3 October 2011)

When I registered for the JavaOne 2011 presentation The Definitive Set of HotSpot Performance Command-line Options, I had no idea how popular that session or my coverage of that session would be. I liked the presentation so much that I purchased the book for which he is the lead author: Java Performance (I hope to write a review of it in coming months). I thought everyone only attended presentations on trendy topics at JavaOne, but I learned that many developers share my same interest in getting better at working with Java in core areas such as performance.

4. JDK 7: New Interfaces, Classes, Enums, and Methods (31 March 2011)

The popularity of JDK 7: New Interfaces, Classes, Enums, and Methods is not surprising given the popularity of Java 7 topics in 2011.

3. HTML5 Date Picker (17 January 2011)

The HTML5 Date Picker post enjoyed advantages of being on a trendy topic (HTML5) and being posted early in the year.

[2.] Seven Indispensable NetBeans Java Hints (9 October 2010)

Although written in late 2009, this post on seven indispensable NetBeans Java Hints remained very popular throughout 2011.

1. JDK 7: The New Objects Class (26 March 2011)

My most popular post by far (more than twice as many hits as the #2 post) has been JDK 7: The New Objects Class. I believe that the popularity of this post is best explained by the fact that the Java 7 java.util.Objects class is generally appealing to Java developers, but is a new "feature" of Java 7 that has perhaps not been as covered as much elsewhere as other features of Java 7.

Conclusion

Common themes associated with my most popular posts of 2011 included trendy topics such as Java 7/8 and HTML5, but also included more core coverage of NetBeans, Java performance, and Java stack traces.

Thứ Sáu, 30 tháng 12, 2011

Rendering HTML Within JavaFX

JavaFX 2.0 allows for inclusion of HTML code within a JavaFX application using JavaFX 2.0's WebView and WebEngine classes from the javafx.scene.web package. This post looks at a very simple example of how this can be done. Much more sophisticated applications could enjoy more interaction between the included HTML content and the JavaFX application itself.

My simple example makes use of a JavaFX 2.0 Accordion control to present multiple Java-related sites that I frequently browse headlines ob for articles and posts to read. Each titled pane in the accordion features a different one of these web sites. The next code listing contains the entire Java class for this application and comes in at fewer than 100 lines of code including comments and white space.

WebViewExample.java

package dustin.examples;

import com.google.common.collect.ImmutableMap;
import java.util.Map;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Accordion;
import javafx.scene.control.TitledPane;
import javafx.scene.paint.Color;
import javafx.scene.web.WebView;
import javafx.scene.web.WebViewBuilder;
import javafx.stage.Stage;

/**
* Simple example of using JavaFX 2.0's WebView class.
*
* @author Dustin
*/
public class WebViewExample extends Application
{
/**
* Provide an instance of a JavaFX 2.0 Accordion control with each titled
* pane in the Accordion featuring a title based on a 'key' value in the
* provided a map and including WebView content of the page referenced by the
* URL in the 'value' portion of the map.
*
* @param titleToUrl Mapping of page titles to their URLs to be used as
* titled pane titles and source of content respectively.
* @return Accordion control with web page-based titled panes.
*/
private Accordion prepareAccordion(final Map<String, String> titleToUrl)
{
final Accordion accordion = new Accordion();
for (final Map.Entry<String,String> webMap : titleToUrl.entrySet())
{
final TitledPane pane =
new TitledPane(webMap.getKey(), buildWebView(webMap.getValue()));
accordion.getPanes().add(pane);
}
return accordion;
}

/**
* Build a simple WebView based on the provided URL.
*
* @param url URL from which content will be rendered in the provided WebView.
* @return WebView whose content is based on web page at provided URL.
*/
private WebView buildWebView(final String url)
{
final WebView webView =
WebViewBuilder.create().prefHeight(450).prefWidth(1000).build();
webView.getEngine().load(url);
return webView;
}

/**
* JavaFX 2.0's Application.start(Stage) method.
*
* @param stage Primary stage.
* @throws Exception Exception thrown during execution of JavaFX application
* stage.
*/
@Override
public void start(final Stage stage) throws Exception
{
stage.setTitle("JavaFX 2.0 WebView Example: Favorite Java Web Sites");
final Group rootGroup = new Group();
final Map<String,String> titleToUrl =
ImmutableMap.<String,String>builder()
.put("Inspired by Actual Events", "http://marxsoftware.blogspot.com/")
.put("JavaWorld", "http://javaworld.com/")
.put("Java.net", "http://java.net/")
.put("Java Lobby", "http://javalobby.com/")
.build();
rootGroup.getChildren().add(prepareAccordion(titleToUrl));
final Scene scene = new Scene(rootGroup, 1000, 600, Color.WHITE);
stage.setScene(scene);
stage.show();
}

/**
* Main function for running this JavaFX example.
*
* @param arguments Command-line arguments: none expected.
*/
public static void main(final String[] arguments)
{
Application.launch(arguments);
}
}

In many ways, the above application works something like a stripped-down web browser. JavaFX does a lot of heavy lifting in processing the HTML source and presenting it just as a web browser would via WebView and an associated WebEngine. Some screen snapshots are shown next of how this application appears when it is run. The first image shows the application when it's initially loaded and the four screen snapshots following that one represent each of the four titled panes being clicked in the accordion.

The links within the presented HTML content can be clicked and the application supports traversal of links. However, significantly greater interaction between the JavaFX application and the rendered HTML can be accomplished using the methods on WebEngine that support interaction with JavaScript [such as getOnStatusChanged()]. The underlying document can also be accessed via WebEngine's documentProperty() and getDocument() methods.

With the increasing importance of HTML5, it's nice that JavaFX has built-in support for interacting with HTML, JavaScript, and the DOM.

Integrating JavaFX 2.0 with Swing and SWT

One of the improvements in JavaFX with JavaFX 2.0 has been greater ease of interoperability with Swing and SWT. Several online resources document how this is done. These include Integrating JavaFX into Swing Applications and SWT Interop. However, in a nice example of effective class-level Javadoc documentation, the respective JavaFX classes javafx.embed.swing.JFXPanel and javafx.embed.swt.FXCanvas each provide a simple code sample of how to use the class to embed JavaFX into Swing or SWT code. In this post, I build upon the code samples provided in these classes' Javadoc documentation to demonstrate JavaFX integration with Swing and SWT.

Both JFXPanel and FXCanvas allow a JavaFX Scene to be set on their instance. The instance of Scene (based on my Simple JavaFX 2.0 Text Example post) to be be used in my examples in this post are provided by the method shown in the next JavaFX-specific code example.

Method Providing a JavaFX Scene for Integration

package dustin.examples;

import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.effect.*;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;

/**
* Simple class intended to be used by two examples of integrating JavaFX with
* Swing and with SWT. Provides single method {@code createScene()} to be used
* by the classes that are examples of integrating Swing with JavaFX and SWT
* with JavaFX.
*
* @author Dustin
*/
public class TextIntegrationSceneCreator
{
/**
* Provides an instance of Scene with JavaFX text examples.
*
* @return Instance of Scene with text examples.
*/
public static Scene createTextScene()
{
final Group rootGroup = new Group();
final Scene scene = new Scene(rootGroup, 800, 400, Color.BEIGE);

final Text text1 = new Text(25, 25, "(2007) JavaFX based on F3");
text1.setFill(Color.CHOCOLATE);
text1.setFont(Font.font(java.awt.Font.SERIF, 25));
rootGroup.getChildren().add(text1);

final Text text2 = new Text(25, 50, "(2010) JavaFX Script Deprecated");
text2.setFill(Color.DARKBLUE);
text2.setFont(Font.font(java.awt.Font.SANS_SERIF, 30));
rootGroup.getChildren().add(text2);

final Text text3 = new Text(25, 75, "(2011) JavaFX to be Open Sourced!");
text3.setFill(Color.TEAL);
text3.setFont(Font.font(java.awt.Font.MONOSPACED, 35));
rootGroup.getChildren().add(text3);

final Text text4 = new Text(25, 125, "(2011) JavaFX to be Standardized");
text4.setFill(Color.CRIMSON);
text4.setFont(Font.font(java.awt.Font.DIALOG, 40));
final Effect glow = new Glow(1.0);
text4.setEffect(glow);
rootGroup.getChildren().add(text4);

final Text text5 = new Text(25, 175, "(Now) Time for JavaFX 2.0!");
text5.setFill(Color.DARKVIOLET);
text5.setFont(Font.font(java.awt.Font.SERIF, FontWeight.EXTRA_BOLD, 45));
final Light.Distant light = new Light.Distant();
light.setAzimuth(-135.0);
final Lighting lighting = new Lighting();
lighting.setLight(light);
lighting.setSurfaceScale(9.0);
text5.setEffect(lighting);
rootGroup.getChildren().add(text5);

final Text text6 = new Text(25, 225, "JavaFX News at JavaOne!");
text6.setFill(Color.DARKGREEN);
text6.setBlendMode(BlendMode.COLOR_BURN);
text6.setFont(Font.font(java.awt.Font.DIALOG_INPUT, FontWeight.THIN, 45));
final Reflection reflection = new Reflection();
reflection.setFraction(1.0);
text6.setEffect(reflection);
rootGroup.getChildren().add(text6);

return scene;
}
}

A JavaFX Scene can be integrated into Swing code via the JavaFX class JFXPanel and its setScene(Scene) method. This is demonstrated in the next code listing, which gets the particular Scene instance from the method in the previous code listing.

JavaFX/Swing Integration with JFXPanel

package dustin.examples;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
* Simple class demonstrating interoperability between Swing and JavaFX. This
* class is adapted from the example provided in the Javadoc documentation for
* {@code javafx.embed.swing.JFXPanel}.
*/
public class SwingJavaFxInteroperabilityDemo
{
private static void initAndShowGUI()
{
// This method is invoked on Swing thread
final JFrame frame = new JFrame("JavaFX / Swing Integrated");
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setVisible(true);

Platform.runLater(new Runnable()
{
@Override
public void run()
{
initFX(fxPanel);
}
});
}

private static void initFX(JFXPanel fxPanel)
{
// This method is invoked on JavaFX thread
final Scene scene = TextIntegrationSceneCreator.createTextScene();
fxPanel.setScene(scene);
}

public static void main(String[] arguments)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
initAndShowGUI();
}
});
}
}

The output of running this simple Java Swing application with embedded JavaFX Scene is shown next.

Integrating SWT with JavaFX is arguably even easier and is demonstrated in the next code listing. As with the Swing integration example, the main approach is to call FXCanvas's setScene(Scene) method.

JavaFX/SWT Integration with FXCanvas

package dustin.examples;

import javafx.embed.swt.FXCanvas;
import javafx.scene.Scene;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

/**
* Simple class demonstrating interoperability between SWT and JavaFX. This
* class is based on the example provided in the Javadoc documentation for
* {@code javafx.embed.swt.FXCanvas}.
*
* @author Dustin
*/
public class SwtJavaFxInteroperabilityDemo
{
public static void main(String[] arguments)
{
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("JavaFX / SWT Integration");
shell.setLayout(new FillLayout());
final FXCanvas canvas = new FXCanvas(shell, SWT.NONE);
final Scene scene = TextIntegrationSceneCreator.createTextScene();
canvas.setScene(scene);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
}

The next screen snapshot shows what this simple SWT application with embedded JavaFX looks like.

The code listings for Swing integration with JavaFX and for SWT integration with JavaFX shown above are only slightly adapted from the Javadoc documentation for the JavaFX classes JFXPanel (Swing) and FXCanvas (SWT). It is nice that these classes provide these examples in their documentation and it is really nice that integration has become so much easier. For more thorough coverage of JavaFX/Swing integration, see Integrating JavaFX into Swing Applications.