This lesson will present the ubiquitous Hello World application - JFCML flavor. This example is presented incrementally, allowing for discussion of important topics. For the impatient, please have a look at the Demo section. This lesson will provide a complete walkthrough of running the JFCML interpreter from the command line; something the demo does not provide. So, if you are impatient, please return here once you have looked at the examples.
<?xml version="1.0" encoding="UTF-16"?> <!DOCTYPE JFCML> <JFCML> </JFCML>
The above code fragment is the minimum requirement for a JFCML document, as enforced by the XML specification. The JFCML element does nothing special, except serve as the container element for the rest of the document. The JFCML element does not represent any Java Object, and the interpreter does nothing when encountering it.
The DOCTYPE element is optional, because JFCML no longer provides a Document Type Definition (DTD). Previous versions of JFCML valued the limiting effect of the DTD, because of limitations in the implementation. Because JFCML now uses Java's Reflection technology, these limitations no longer exist. In fact, for document validation, a DTD is probably no longer the appropriate technology. Eventually, an XSL schema may be provided for document validation.
<?xml version="1.0" encoding="UTF-16"?> <!DOCTYPE JFCML> <JFCML> <Import package="javax.swing"/> <JRootPane> </JRootPane> </JFCML>
Although not explicitly required, most JFCML documents will contain the JRootPane element. The JRootPane is used by all top-level Swing containers as the root node of your Java application's component tree. Using a JRootPane as your top-level container will enable the JFCML interpreter to render your document as a JApplet, JFrame, JWindow, or JDialog. Top-level AWT containers do not provide this abstraction; therefore JFCML provides a custom 'RootPane' element, allowing this very handy indirection for AWT containers.
Since JRootPane is contained in the javax.swing package, the above JFCML document requires an "Import" element; this element is used like the Java "import" keyword. Further, a JFCML document and a Java source file have the same rules about how they must be used: each package referenced by the source file must be explicity imported, else package qualified class names must be used.
<?xml version="1.0" encoding="UTF-16"?> <!DOCTYPE JFCML> <JFCML> <Import package="javax.swing"/> <JRootPane> <ContentPane> <JLabel setText="'Hello World'"/> </ContentPane> </JRootPane> </JFCML>
One of the primary tasks when creating a GUI application is to describe your application's component tree. This is also the primary function of all XUL's, including JFCML. Indeed XML is an excellent tool for this task, because an XML document "is a" tree. To build this tree in Java, the programmer would configure their Components, and then "add" them to Containers. This is also the case with JFCML: each XML element represents a Java Component or Object, and the attributes of each XML element represent the properties of the Java Component.
In Java, the JRootPane is the container for the JMenuBar, the "ContentPane", and the "GlassPane". In the example above, a JLabel is added to the ContentPane. This JLabel contains the "setText" attribute, with the value 'Hello World'. When JFCML encounters this or any other attributes, it will try map the attribute name to a Field or Method in the current Object, and pass in the argument(s). In this case, the string "Hello World" will be passed to this JLabel's setText method.
Generally, JFCML will rely on a scripting engine to evaluate the argument(s). JFCML can interface with most major scripting languages, and additionally provides it's own: JFCMLScript. All examples on this page will use JFCMLScript. JFCMLScript requires string literals to be delimited by single quotation marks, as the above example demonstrates.
<?xml version="1.0" encoding="UTF-16"?> <!DOCTYPE JFCML> <JFCML> <Import package="javax.swing"/> <Import class="java.awt.Dimension"/> <JFrame setSize="new Dimension(200,200)" setDefaultCloseOperation="JFrame.EXIT_ON_CLOSE"/> <JRootPane> <ContentPane> <JLabel setText="'Hello World'"/> </ContentPane> </JRootPane> </JFCML>
Because we will be running this example in a JFrame, we will need to specify the frame's behavior when it receives the WINDOW_CLOSING event. In AWT, this was accomplished by adding a WindowListener to the top level window. Swing makes this much simpler by defining a few common behaviors, so the user is not required to implement this interface.
In this case, we have chosen the EXIT_ON_CLOSE behavior by passing this constant to the JFrame's setDefaultCloseOperation method. We have also chosen a size for the window by creating a Dimension Object and passing to it to JFrame's setSize method. The Dimension class is in thw AWT package, therefore an additional import statement is needed.
Note how the JFrame element in this example is an empty element. It would also have been correct to make the JRootPane a child element of the JFrame. However, we will allow JFCML to map the JRootPane to the top level window. This JFCML document could also be run in a JApplet without modification; the JFrame element could simply be ignored.
Unlike many similar tools, JFCML does not require the programmer to implement a Java class. It is possible to interpret a JFCML document from the command line. Name the example "hello.jfcml" and place it in the same folder as the JFCML interpreter. It may be run with the command:
java -jar jfcml.jar -jframe hello.jfcml
JFCML's main class is highly flexible, and allows the user to render the JFCML document as any "top-level" AWT or Swing container type, including applets. It is even possible to create your own "top-level" container class, and use that, right from the command line:
java -jar jfcml.jar -class package.name.MyContainerClass hello.jfcml
Creating your own container class is a convenient way of adding additional functionality to JFCML. Any public methods defined in the class will be available for use in the JFCML document.