Wednesday Sep 09, 2009

Follow Scott on Twitter!

Hey everyone, this is Scott Hommel. I've been a member of the docs team here at Sun for the past decade, working on both the JDK docs and the Java Tutorial. Since '07 I've been assigned exclusively to JavaFX (http://www.javafx.com). I've set up a twitter account at http://www.twitter.com/scotthommel so if you've ever been curious about the day-to-day workings of a technical writer, sign up to "follow" what I'm working on. It'll give you the inside scoop on what docs are coming out next. With enough followers, perhaps other writers will start "tweeting" as well.

-- Scott Hommel

Wednesday May 27, 2009

Just released -- Java Tutorials update

To coincide with the JDK7 Preview Release and JavaOne, we have just published an updated version of the Java Tutorials. Besides fixing many typos and errors that you have reported, this release includes:

  • An entirely reworked File I/O lesson, featuring NIO.2. This functionality is part of JDK7, which is available now through the Open JDK project on java.net.
  • A new specialized trail covering Sockets Direct Protocol, also new in JDK7.
  • A new facility for gathering feedback about the tutorial. At the bottom of each tutorial page, under the "Discuss" heading, you can leave a publicly viewable, blog-style comment. Let us know what you think about the inclusion of this JS-Kit mechanism.

Thanks, as always, for your feedback. It helps us improve the tutorial!

-- Sharon Zakhour

Tuesday Feb 03, 2009

JavaBat -- Java Practice Programs

Wow, a very cool website was just brought to my attention. Nick Parlante, of Stanford, has pulled together a website where you can hone your Java skills.

Created with the theory that you learn by doing and the more you do it, the better you get, JavaBat provides a set of programming examples that give you immediate feedback. You can work through several examples in an hour — it compiles and runs your code using a variety of parameters so you can see where it fails. At the end, you can hop over to the "done" page and view your stats. Want to test your skills in a friendly, good-natured competition? Here ya go. :)

JavaBat is one of the neatest, free Java resources I've seen in a long time!

-- Sharon Zakhour

Thursday Jan 15, 2009

Inverse Kinematics Demo

Sun engineer Michael Heinrichs recently wrote a great animation demo that uses inverse kinematics to animate JavaFX objects. Check it out on his blog and feel free to leave a comment!

-- Scott Hommel

Friday Dec 12, 2008

JavaFX Coffee Cup

So the JavaFX™ SDK 1.0 has shipped. I thought that now would be a fun time to try out some of its graphics capabilities. I know that its graphics are really slick... but how easy are they to program? Do you need to be a graphics expert to figure it all out, or can anyone just pick it up and learn?

As for my background, I'm a technical writer and general-purpose computer programmer. I am not a software engineer, graphic designer, or GUI expert. Because of that I'm probably the ideal person to test drive the usability of GUI coding with the SDK. The challenge to myself was to take a single afternoon and code up something "impressive"; it didn't matter what, I just wanted it to have a 3D feel with modern visual/lighting effects like what I see in the SDK demos.

So the first thing I did was to read the GUI tutorial, which quickly brought me up to speed on the basics. (Those completely new to the JavaFX Script programming language will want to first read the core tutorial as well.) I then went to the web, looking for information on drawing 3D shapes in general.

I came across this article, which builds a 3D coffee cup using a freeware vector graphics drawing program called inkscape. Having a limited GUI background, this was exactly the kind of breakdown that I needed. It explained how to make "3D" looking objects from basic 2D shapes, filled in with various color gradients. The challenge to myself was to basically "port" their tool instructions to equivalent calls in the API. By the end of the afternoon, I'd made this cool looking cup:

Here's how I did it...

Making the Frame

Setting up the basic application frame was super easy to do. JavaFX technology lets you "group" multiple objects together, so I made one group for the plate, and another for the cup. These two groups will contain the graphical objects to be rendered on screen:

import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.Group;

def plateGroup = Group {
     // The group of objects forming the "plate" will go here
}

def cupGroup = Group {
    // The group of objects forming the "cup" will go here
}

Stage {
    title: "Coffee Cup"
    visible: true
    scene: Scene {
         width: 500
         height: 500
         content: [plateGroup,cupGroup]
     }
}

There's nothing to display yet, but the code is organized, and that's an important first step. I've used the def keyword to assign these groups to individual variables; this makes it easier to "unplug" a finished group (i.e. the plate) to work on the other (the cup) in isolation, if need be.

Making the Plate

The first step in making the plate was to draw an Ellipse, filled with a RadialGradient that spans three colors (Color.WHITESMOKE, Color.LIGHTGRAY, and Color.DARKGREY):

import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.\*;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;

def plateGroup = Group {

     translateX: 250
     translateY: 300

     content: [
          Ellipse {centerX: 0 centerY: 0  radiusX: 170 radiusY: 50
               fill: RadialGradient{
                         centerX: 0.5 centerY: 0.75
                         stops: [Stop {offset: 0.0 color: Color.WHITESMOKE},
                                 Stop {offset: 0.5 color: Color.LIGHTGRAY},
                                 Stop {offset: 1.0 color: Color.DARKGRAY}]
               } 
          } 
     ] 
}

def cupGroup = Group {
    // The group of objects forming the "cup" will go here
}

Stage {
    title: "Coffee Cup"
    visible: true
    scene: Scene {
         width: 500
         height: 500
         content: [plateGroup,cupGroup]
     }
}

The translateX and translateY variables of the Group object proved useful for moving the entire group around on screen. I found that getting the exact values for the gradient was just a matter of trial and error. There are a number of different settings that all looked good; finding something that looked "right" was just a matter of plugging in different values and recompiling the program.

Next I added a dark gray ellipse below the plate, and another thin ellipse to make the lip (giving it a 3D feel):

import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.\*;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;

def plateGroup = Group {

translateX: 250
translateY: 300

 content: [ 

          // The gray ellipse under the plate
          Ellipse{centerX: 0 centerY: 10 radiusX: 160 radiusY: 50 fill: Color.DIMGRAY},

          // The thin "lip" of the plate (provides a sense of 3D)
          Ellipse{centerX: 0 centerY: 3  radiusX: 170 radiusY: 50 fill: Color.LAVENDER}, 

          // The large plate ellipse
          Ellipse{centerX: 0 centerY: 0  radiusX: 170 radiusY: 50
          fill: RadialGradient{
                    centerX: 0.5 centerY: 0.75
                    stops:[Stop {offset: 0.0 color: Color.WHITESMOKE},
                           Stop {offset: 0.5 color: Color.LIGHTGRAY},
                           Stop {offset: 1.0 color: Color.DARKGRAY}]
               }
          }
     ]
}

def cupGroup = Group {
    // The group of objects forming the "cup" will go here
}

Stage {
    title: "Coffee Cup"
    visible: true
    scene: Scene {
         width: 500
         height: 500
         content: [plateGroup,cupGroup]
     }
}

Since GUI objects are rendered in the order they appear in the source code, I put the main plate ellipse last so that it would cover the tops of all the others. Again, finding the exact values was just a matter of experimentation.

Finally, I recessed the center of the plate:

import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.\*;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;

def plateGroup = Group {

translateX: 250
translateY: 300

 content: [

          // The gray ellipse under the plate
          Ellipse{centerX:0 centerY:10 radiusX:160 radiusY:50 fill:Color.DIMGRAY},

          // The thin "lip" of the plate (provides a sense of 3D)
          Ellipse{centerX:0 centerY:3  radiusX:170 radiusY:50 fill:Color.LAVENDER},

          // The large plate ellipse
          Ellipse{centerX:0 centerY:0  radiusX:170 radiusY:50
          fill:RadialGradient{
                    centerX:0.5 centerY:0.75
                    stops:[Stop {offset: 0.0 color: Color.WHITESMOKE},
                           Stop {offset: 0.5 color: Color.LIGHTGRAY},
                           Stop {offset: 1.0 color: Color.DARKGRAY}]
               }
          },

         // Recessed plate center
           Ellipse{centerX: 0 centerY: 5 radiusX: 90 radiusY: 22
                fill: RadialGradient{
                          centerX: 0.5 centerY: 0.75
                          stops:[Stop {offset: 0.0 color: Color.BLACK},
                                 Stop {offset: 0.4 color: Color.LIGHTGRAY},
                                 Stop {offset: 1.0 color: Color.GHOSTWHITE}]
                     }
          }
     ]
}

def cupGroup = Group {
    // The group of objects forming the "cup" will go here
}

Stage {
    title: "Coffee Cup"
    visible: true
    scene: Scene {
         width: 500
         height: 500
         content: [plateGroup,cupGroup]
     }
}

Without this dark shadow, the cup bottom would be hard to see when it's finally in place. In the end this darkened area will be more subtle because the cup will be hiding most of it.

Making the Cup

To make the cup, I just started with a Circle, giving it the the same kind of gradient as used in the plate. My approach here was to treat the cup like a blob of clay. The API contains powerful built-in transforms that I can later use to "stretch" the cup into shape. How cool is that?

import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.\*;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;

def plateGroup = Group {

translateX: 250
translateY: 300

 content: [

          // The gray ellipse under the plate
          Ellipse{centerX:0 centerY:10 radiusX:160 radiusY:50 fill:Color.DIMGRAY},

          // The thin "lip" of the plate (provides a sense of 3D)
          Ellipse{centerX:0 centerY:3  radiusX:170 radiusY:50 fill:Color.LAVENDER},

          // The large plate ellipse
          Ellipse{centerX:0 centerY:0  radiusX:170 radiusY:50
          fill:RadialGradient{
                    centerX:0.5 centerY:0.75
                    stops:[Stop {offset: 0.0 color: Color.WHITESMOKE},
                           Stop {offset: 0.5 color: Color.LIGHTGRAY},
                           Stop {offset: 1.0 color: Color.DARKGRAY}]
               }
          },

         // Recessed plate center
           Ellipse{centerX: 0 centerY: 5 radiusX: 90 radiusY: 22
                fill: RadialGradient{
                          centerX: 0.5 centerY: 0.75
                          stops:[Stop {offset: 0.0 color: Color.BLACK},
                                 Stop {offset: 0.4 color: Color.LIGHTGRAY},
                                 Stop {offset: 1.0 color: Color.GHOSTWHITE}]
                     }
          }
     ]
}

def cupGroup = Group {

     translateX: 152
     translateY: 20

     content: [
               // Cup body
               Circle {centerX: 100  centerY: 100 radius: 50
                    fill: RadialGradient {
                               centerX: 0.4 centerY: 0.0 focusX: 0.5 focusY: .65, proportional:true
                               stops: [Stop {offset: 0.0 color: Color.GHOSTWHITE},
                                       Stop {offset: 1.0 color: Color.SILVER}]
               }
          }
     ]
}


Stage {
    title: "Coffee Cup"
    visible: true
    scene: Scene {
         width: 500
         height: 500
         content: [plateGroup,cupGroup]
     }
}

To make this ball more "cup-like", I next placed a white rectangle over the top of the circle to flatten it out:

import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.\*;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;

def plateGroup = Group {

translateX: 250
translateY: 300

 content: [

          // The gray ellipse under the plate
          Ellipse{centerX:0 centerY:10 radiusX:160 radiusY:50 fill:Color.DIMGRAY},

          // The thin "lip" of the plate (provides a sense of 3D)
          Ellipse{centerX:0 centerY:3  radiusX:170 radiusY:50 fill:Color.LAVENDER},

          // The large plate ellipse
          Ellipse{centerX:0 centerY:0  radiusX:170 radiusY:50
          fill:RadialGradient{
                    centerX:0.5 centerY:0.75
                    stops:[Stop {offset: 0.0 color: Color.WHITESMOKE},
                           Stop {offset: 0.5 color: Color.LIGHTGRAY},
                           Stop {offset: 1.0 color: Color.DARKGRAY}]
               }
          },

         // Recessed plate center
           Ellipse{centerX: 0 centerY: 5 radiusX: 90 radiusY: 22
                fill: RadialGradient{
                          centerX: 0.5 centerY: 0.75
                          stops:[Stop {offset: 0.0 color: Color.BLACK},
                                 Stop {offset: 0.4 color: Color.LIGHTGRAY},
                                 Stop {offset: 1.0 color: Color.GHOSTWHITE}]
                     }
          }
     ]
}

def cupGroup = Group {

     translateX: 152
     translateY: 20

     content: [
               // Cup body
               Circle {centerX: 100  centerY: 100 radius: 50
                    fill: RadialGradient {
                               centerX: 0.4 centerY: 0.0 focusX: 0.5 focusY: .65, proportional:true
                               stops: [Stop {offset: 0.0 color: Color.GHOSTWHITE},
                                       Stop {offset: 1.0 color: Color.SILVER}]
               }
          },


               // Cut top of cup
               Rectangle{stroke: Color.WHITE fill: Color.WHITE 
                         x: 25 y: 50 width: 150 height: 50} 
     ]
}

Stage {
    title: "Coffee Cup"
    visible: true
    scene: Scene {
         width: 500
         height: 500
         content: [plateGroup,cupGroup]
     }
}

After that, I just added a couple more ellipses to make the outer and inner rims:

import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.\*;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;

def plateGroup = Group {

translateX: 250
translateY: 300

 content: [

          // The gray ellipse under the plate
          Ellipse{centerX:0 centerY:10 radiusX:160 radiusY:50 fill:Color.DIMGRAY},

          // The thin "lip" of the plate (provides a sense of 3D)
          Ellipse{centerX:0 centerY:3  radiusX:170 radiusY:50 fill:Color.LAVENDER},

          // The large plate ellipse
          Ellipse{centerX:0 centerY:0  radiusX:170 radiusY:50
          fill:RadialGradient{
                    centerX:0.5 centerY:0.75
                    stops:[Stop {offset: 0.0 color: Color.WHITESMOKE},
                           Stop {offset: 0.5 color: Color.LIGHTGRAY},
                           Stop {offset: 1.0 color: Color.DARKGRAY}]
               }
          },

         // Recessed plate center
           Ellipse{centerX: 0 centerY: 5 radiusX: 90 radiusY: 22
                fill: RadialGradient{
                          centerX: 0.5 centerY: 0.75
                          stops:[Stop {offset: 0.0 color: Color.BLACK},
                                 Stop {offset: 0.4 color: Color.LIGHTGRAY},
                                 Stop {offset: 1.0 color: Color.GHOSTWHITE}]
                     }
          }
     ]
}

def cupGroup = Group {

     translateX: 152
     translateY: 20

     content: [
               // Cup body
               Circle {centerX: 100  centerY: 100 radius: 50
                    fill: RadialGradient {
                               centerX: 0.4 centerY: 0.0 focusX: 0.5 focusY: .65, proportional:true
                               stops: [Stop {offset: 0.0 color: Color.GHOSTWHITE},
                                       Stop {offset: 1.0 color: Color.SILVER}]
               }
          },

               // Cut top of cup
               Rectangle{stroke: Color.WHITE fill: Color.WHITE 
                         x: 25 y: 50 width: 150 height: 50},

               // Outer rim
               Ellipse{fill: Color.WHITE centerX: 100 centerY: 100 radiusX: 50 radiusY: 8},

               // Inner rim
               Ellipse{centerX: 100 centerY: 100 radiusX: 48 radiusY: 7 //inner rim
                       fill: RadialGradient {
                                             centerX: 0.4 centerY: 0.0 focusX: 0.5 focusY:.4, proportional:true
                                             stops: [Stop {offset: 0.0 color: Color.GHOSTWHITE},
                                                     Stop {offset: 1.0 color: Color.SILVER}]
                       }
               }
     ]
}

Stage {
    title: "Coffee Cup"
    visible: true
    scene: Scene {
         width: 500
         height: 500
         content: [plateGroup,cupGroup]
     }
}

Things are looking good! But the cup is still too small. So to make the cup "grow", I just scaled the entire cup group upwards. I actually scaled the y axis slightly more, so as to squish the cup inwards a little to shape it more like an egg:

import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.\*;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;

def plateGroup = Group {

translateX: 250
translateY: 300

 content: [

          // The gray ellipse under the plate
          Ellipse{centerX:0 centerY:10 radiusX:160 radiusY:50 fill:Color.DIMGRAY},

          // The thin "lip" of the plate (provides a sense of 3D)
          Ellipse{centerX:0 centerY:3  radiusX:170 radiusY:50 fill:Color.LAVENDER},

          // The large plate ellipse
          Ellipse{centerX:0 centerY:0  radiusX:170 radiusY:50
          fill:RadialGradient{
                    centerX:0.5 centerY:0.75
                    stops:[Stop {offset: 0.0 color: Color.WHITESMOKE},
                           Stop {offset: 0.5 color: Color.LIGHTGRAY},
                           Stop {offset: 1.0 color: Color.DARKGRAY}]
               }
          },

         // Recessed plate center
           Ellipse{centerX: 0 centerY: 5 radiusX: 90 radiusY: 22
                fill: RadialGradient{
                          centerX: 0.5 centerY: 0.75
                          stops:[Stop {offset: 0.0 color: Color.BLACK},
                                 Stop {offset: 0.4 color: Color.LIGHTGRAY},
                                 Stop {offset: 1.0 color: Color.GHOSTWHITE}]
                     }
          }
     ]
}

def cupGroup = Group {

     translateX: 152
     translateY: 20
     scaleX: 3.0
     scaleY: 4.0

     content: [
               // Cup body
               Circle {centerX: 100  centerY: 100 radius: 50
                    fill: RadialGradient {
                               centerX: 0.4 centerY: 0.0 focusX: 0.5 focusY: .65, proportional:true
                               stops: [Stop {offset: 0.0 color: Color.GHOSTWHITE},
                                       Stop {offset: 1.0 color: Color.SILVER}]
               }
          },

               // Cut top of cup
               Rectangle{stroke: Color.WHITE fill: Color.WHITE 
                         x: 25 y: 50 width: 150 height: 50},

               // Outer rim
               Ellipse{fill: Color.WHITE centerX: 100 centerY: 100 radiusX: 50 radiusY: 8},

               // Inner rim
               Ellipse{centerX: 100 centerY: 100 radiusX: 48 radiusY: 7 //inner rim
                       fill: RadialGradient {
                                             centerX: 0.4 centerY: 0.0 focusX: 0.5 focusY:.4, proportional:true
                                             stops: [Stop {offset: 0.0 color: Color.GHOSTWHITE},
                                                     Stop {offset: 1.0 color: Color.SILVER}]
                       }
               },
     ]
}

Stage {
    title: "Coffee Cup"
    visible: true
    scene: Scene {
         width: 500
         height: 500
         content: [plateGroup,cupGroup]
     }
}

Filling the Cup

Now it's time to fill the cup! For this I made a custom shape from the intersection of the inner rim and a new coffee-colored ellipse. The built-in ShapeIntersect class makes this a trivial matter:

import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.\*;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;

def plateGroup = Group {

translateX: 250
translateY: 300

 content: [

          // The gray ellipse under the plate
          Ellipse{centerX:0 centerY:10 radiusX:160 radiusY:50 fill:Color.DIMGRAY},

          // The thin "lip" of the plate (provides a sense of 3D)
          Ellipse{centerX:0 centerY:3  radiusX:170 radiusY:50 fill:Color.LAVENDER},

          // The large plate ellipse
          Ellipse{centerX:0 centerY:0  radiusX:170 radiusY:50
          fill:RadialGradient{
                    centerX:0.5 centerY:0.75
                    stops:[Stop {offset: 0.0 color: Color.WHITESMOKE},
                           Stop {offset: 0.5 color: Color.LIGHTGRAY},
                           Stop {offset: 1.0 color: Color.DARKGRAY}]
               }
          },

         // Recessed plate center
           Ellipse{centerX: 0 centerY: 5 radiusX: 90 radiusY: 22
                fill: RadialGradient{
                          centerX: 0.5 centerY: 0.75
                          stops:[Stop {offset: 0.0 color: Color.BLACK},
                                 Stop {offset: 0.4 color: Color.LIGHTGRAY},
                                 Stop {offset: 1.0 color: Color.GHOSTWHITE}]
                     }
          }
     ]
}

def cupGroup = Group {

     translateX: 152
     translateY: 20
     scaleX: 3.0
     scaleY: 4.0

     content: [
               // Cup body
               Circle {centerX: 100  centerY: 100 radius: 50
                    fill: RadialGradient {
                               centerX: 0.4 centerY: 0.0 focusX: 0.5 focusY: .65, proportional:true
                               stops: [Stop {offset: 0.0 color: Color.GHOSTWHITE},
                                       Stop {offset: 1.0 color: Color.SILVER}]
               }
          },

          // Cut top of cup
          Rectangle{stroke: Color.WHITE fill: Color.WHITE 
                    x: 25 y: 50 width: 150 height: 50},

          // Outer rim
          Ellipse{fill: Color.WHITE centerX: 100 centerY: 100 radiusX: 50 radiusY: 8},

          // Inner rim
          Ellipse{centerX: 100 centerY: 100 radiusX: 48 radiusY: 7 //inner rim
                  fill: RadialGradient {
                                        centerX: 0.4 centerY: 0.0 focusX: 0.5 focusY:.4, proportional:true
                                        stops: [Stop {offset: 0.0 color: Color.GHOSTWHITE},
                                                Stop {offset: 1.0 color: Color.SILVER}]
                  }
          },
          
         // Create "coffee in cup" by intersecting coffee ellipse with inner rim ellipse
         ShapeIntersect {

              fill: Color.SADDLEBROWN

              //Inner Rim
              a: Ellipse{centerX:100 centerY:100 radiusX:48 radiusY:7} // inner rim dimensions

              //Coffee
              b: Ellipse{centerX:100 centerY:102 radiusX:46 radiusY:6} // coffee dimensions
         }
     ]
}

Stage {
    title: "Coffee Cup"
    visible: true
    scene: Scene {
         width: 500
         height: 500
         content: [plateGroup,cupGroup]
     }
}

And finally, I gave the whole thing a little extra class by setting the background to black:

import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.paint.Color;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.\*;
import javafx.scene.paint.Stop;
import javafx.scene.paint.RadialGradient;

def BGCOLOR = Color.BLACK;

def plateGroup = Group {

     translateX: 250
     translateY: 300

     content: [

          // The gray ellipse under the plate
          Ellipse{centerX:0 centerY:10 radiusX:160 radiusY:50 fill:Color.DIMGRAY},

          // The thin "lip" of the plate (provides a sense of 3D)
          Ellipse{centerX:0 centerY:3  radiusX:170 radiusY:50 fill:Color.LAVENDER},

          // The large plate ellipse
          Ellipse{centerX:0 centerY:0  radiusX:170 radiusY:50
          fill:RadialGradient{
                    centerX:0.5 centerY:0.75
                    stops:[Stop {offset: 0.0 color: Color.WHITESMOKE},
                           Stop {offset: 0.5 color: Color.LIGHTGRAY},
                           Stop {offset: 1.0 color: Color.DARKGRAY}]
               } 
          },

          // Recessed plate center
           Ellipse{
                centerX:0 centerY:5 radiusX:90 radiusY:22
                fill:RadialGradient{
                          centerX:0.5 centerY:0.75
                          stops:[Stop {offset: 0.0 color: Color.BLACK},
                                 Stop {offset: 0.4 color: Color.LIGHTGRAY},
                                 Stop {offset: 1.0 color: Color.GHOSTWHITE}]
                     }
          }
     ] 
} 

def cupGroup = Group {
  
     translateX: 152
     translateY: 20
     scaleX: 3.0
     scaleY: 4.0

     content: [
               // Cup body
               Circle {centerX: 100  centerY: 100 radius: 50
                    fill: RadialGradient {
                               centerX: 0.4 centerY: 0.0 focusX: 0.5 focusY:.65, proportional:true
                               stops: [Stop {offset: 0.0 color: Color.GHOSTWHITE},
                                       Stop {offset: 1.0 color: Color.SILVER}]
                             }
                      },

               // Cut top of cup
               Rectangle{stroke: BGCOLOR fill: BGCOLOR
                         x:25 y:50 width:150 height:50},

               // Outer rim
               Ellipse{fill: Color.WHITE centerX:100 centerY:100 radiusX:50 radiusY:8},

               // Inner rim
               Ellipse{centerX:100 centerY:100 radiusX:48 radiusY:7 //inner rim
                       fill: RadialGradient {
                                             centerX: 0.4 centerY: 0.0 focusX: 0.5 focusY:.4, proportional:true
                                             stops: [Stop {offset: 0.0 color: Color.GHOSTWHITE},
                                                     Stop {offset: 1.0 color: Color.SILVER}]
                       }
               },

               // Create "coffee in cup" by intersecting coffee ellipse with inner rim ellipse
               ShapeIntersect {

                    fill:Color.SADDLEBROWN

                    //Inner Rim
                    a: Ellipse{centerX:100 centerY:100 radiusX:48 radiusY:7} // inner rim dimensions

                    //Coffee
                    b: Ellipse{centerX:100 centerY:102 radiusX:46 radiusY:6} // coffee dimensions
               }
     ]
}

Stage {
    title: "Coffee Cup"
    width: 500
    height: 500
    visible: true
    scene: Scene {
         fill: BGCOLOR
         content: [plateGroup,cupGroup]
     }
}

Conclusion and Future Steps

In conclusion, I found my first attempt at GUI programming with the 1.0 SDK to be quite successful, and ultimately a lot of fun. The declarative programming model is easy to use. Creating sophisticated visual effects becomes almost effortless. The most time-consuming part of the entire project was just tweaking the different gradient values to get the lighting the way I wanted. But the declarative nature of this language really made the actual programming a breeze. I'm really looking forward to what this language can do when it's placed into the hands of real graphic designers!

I'm stopping here because this is what I was able to accomplish in a single afternoon. From here the cup needs a handle and some extra decorations on its face. It would also be great to use key frame animation to add in a steam effect. If you're reading this and would like to add them in, feel free to post your solutions!

-- Scott Hommel

Tuesday Dec 09, 2008

JavaFX on Facebook

Some folks at Sun have created the first JavaFX application to run on Facebook. If you have a Facebook account, please try it out! (And if you don't have a Facebook account, it's free.)

The picture puzzle app runs on any browser supported by JavaFX, although you get more functionality if you are running JRE 6u10 or better.

To play with the jigsaw puzzle:

  1. Login to Facebook.
  2. Search on JavaFX and from the results select JavaFXPicturePuzzle — it should be the second item listed. (It's located at http://apps.facebook.com/javafxpicturepuzzle/Puzzle.)
  3. Select Go to Application and accept the security questions when prompted.
  4. Bookmark the app so that you can easily find it again — the Bookmark JavaFXPicturePuzzle button is at the bottom of the page.
  5. Please share with your friends by selecting the Share with Friends tab near the top of the page.

Let us know what you think!

-- Sharon Zakhour

Monday Dec 08, 2008

JavaFX is here!!

Released late last week, JavaFX 1.0 is here!!!

My team created two of the tutorials for JavaFX:

Please check it out and let us know what you think!

Sharon Zakhour

Tuesday Sep 02, 2008

Changing the java.ext.dirs Property

We received a question on the java tutorials alias that isn't covered in the Extension Mechanism tutorial. We were asked if there is a way to set the ext path using an environment variable. Something along the lines of:
    export JAVA_EXT_PATH="/opt/MyProduct/java-ext"

No, there is no environment variable, but there is the java.ext.dirs system property. For example:

    java -Djava.ext.dirs=/foo/bar/baz:/bleem/grumpf MyApp 
See the Extension Mechanism Architecture spec and search for "java.ext.dirs" and you can read a bit more. In particular, note that the path separator (':' above) is platform dependent, so it would be a semi colon on Windows.

Thanks to Maxim Vexler for asking the question and especially to Dave Bristor in software for answering it. :-)

-- Sharon Zakhour

Tuesday Aug 12, 2008

Changing the Java Web Start Splash Screen

Java applications that are launched with Java Web Start have a default splash screen that displays before your application is ready to run on your system. For JavaSE 6 Update 10, this splash screen looks like the following:

You can change this splash image to one with your own GIF, JPG, or PNG file. The first time Java Web Start launches your application you will see the default Java cup logo image. All subsequent launches will display your splash image.

Java Network Launch Protocol (JNLP)

All applications launched with Java Web Start technology have an associated JNLP file (a file name with a .jnlp extension). You need to edit this JNLP file and specify the image you want to use for your splash screen. Essentially, you add one line to the <information> element within your JNLP file:

<icon href="mysplash.jpg" kind="splash"/>

where the mysplash.jpg file is the image file you want to use to replace the default splash image.

Note: For more information about JNLP, refer to the Java Web Start Developers Guide or the JNLP specification.

Here is an example JNLP file with this <icon> line added to the <information> element:

<?xml version="1.0" encoding="utf-8"?>
<!-- JNLP File for ButtonDemo -->
        <jnlp
     spec="1.0+"
     codebase="http://java.sun.com/docs/books/tutorialJWS/uiswing/components"
     href="ButtonDemo.jnlp">
     <information>
       <title>ButtonDemo</title>
       <vendor>The Java(tm) Tutorial: Sun Microsystems, Inc.</vendor>
       <homepage href="http://java.sun.com/docs/books/tutorial/uiswing/examples/components/index.html#ButtonDemo"/>
       <icon href="mysplash.jpg" kind="splash"/>
       <description>ButtonDemo</description>
       <description kind="short">Demonstrates use of buttons within containers</description>
       <offline-allowed/>
     </information>
     <resources>
       <j2se version="1.6+"/>
       <jar href="ButtonDemo.jar"/>
     </resources>
     <application-desc main-class="components.ButtonDemo"/>
   </jnlp> 

The JAR file with your application is stored on the web server in a location specified by the codebase value in the JNLP file. The path you specify for your splash image is relative to the codebase value. So for example, in the JNLP file above, the file mysplash.jpg needs to be stored in the directory specified by the codebase.

Try It Out

To see this in action, try this Java programming language ButtonDemo. When you first launch it with Java Web Start technology, the default Java cup logo splash screen displays on your screen before the application appears on your desktop. When you launch the application a second time, the image for the file mysplash.jpg will display before the ButtonDemo application appears on your desktop.

-- Debra Scott

Thursday Jul 31, 2008

JavaFX Preview SDK is now LIVE!

"JavaFX is a family of products for creating rich internet applications (RIA) with immersive media and content, across all the screens of your life. It includes a runtime and a tools suite that web scripters, designers and developers can use to quickly build and deliver the next generation of rich interactive applications for desktop, mobile devices, TV, and other platforms."

http://javafx.com
http://java.sun.com/javafx
https://openjfx.dev.java.net
http://blogs.sun.com/javafx

Thursday Jun 19, 2008

Thumbnail Tooltip Demo

Frequent contributor to the tutorial forum, Collin Fagan, has created a new demo that combines bits of other tutorial demos plus some interesting new functionality.

ThumbnailTooltipDemo features a tabbed pane containing three tabs. The first tab shows a tree, the second a table, and the third contains a grid of images. What's interesting here is that when you hover the mouse over one of the tabs, you see a pictorial tooltip representing the contents of that tab. The tooltip is dynamically generated, so if the appearance of the pane changes, by highlighting text, for example, that change is reflected in the tooltip.

You can see the forum thread or check out the wiki page with the source code.

Very cool, Collin!

-- Sharon Zakhour

Wednesday Jun 04, 2008

1.4 Version of the Java Tutorials

Some of you don't have the luxury of using the newer releases of the JDK and we are occasionally asked for an older version -- particularly release 1.4 of the JDK. Before we moved to the Sun Download Center, we did have a page that contained some, but not all, of the older versions of the tutorial.

I went to my pile of old published tutorials and extracted the 1.4 version from the cd included with the Second Edition of The Swing Tutorial. I've made it available through the Java Tutorials Community Portal: tutorial_1.4.zip.

Enjoy!

-- Sharon Zakhour

Tuesday May 20, 2008

Preparing for Java Programming Language Certification

When we updated the core Java Tutorial to JDK 6, we included a page designed to help those who are studying for Java Programming Language Certification. This study guide calls out which portions of the tutorial are relevant to the testing objectives -- it is by no means comprehensive. Nor does it discuss the test and what to expect.

We still sometimes receive questions on the tutorial feedback alias asking how to prepare for the Java Programmer Certification test. The book strongly recommended by our Java instructors and course developers is the Complete Java 2 Certification Study Guide by Philip Heller.

You can follow this thread on the Java Tutorials Community forum.

-- Sharon Zakhour

Friday May 16, 2008

DefaultTreeModel -- Adding, Removing and Updating Nodes

Many moons ago I had a discussion with Collin Fagan (Java Tutorial contributor and all around helpful guy) about the fact that I had seen some requests for a tutorial on how to add, remove and update nodes in a DefaultTreeModel.

Collin wasted no time creating such an example. Unfortunately, resources being what they are, I wasn't able to get engineering cycles for reviewing the example. Because we generally don't include material that hasn't been reviewed by engineering, it was backburnered.

Meanwhile, Collin posted his example and some accompanying text, The Secret Life of a DefaultTreeModel on JavaLobby.

Collin has now posted his example on the JavaTutorials forum!

When you compile and run the example (it will run under JDK 5) it brings up a panel containing a tree with a root node. When you open the root node you'll see three child nodes. At this point you can right-click any of the nodes (control-click on a Mac) and you can add 50 children to the current selection, remove the current selection, or modify the text on the current selection.

Thanks for this very useful example, Collin!

-- Sharon Zakhour

Tuesday May 13, 2008

JTable: Freezing a column while scrolling the others

Have you ever needed to create a table that is too wide for the view so it requires a horitzonal scrollbar? OK, that's pretty routine. But have you then wanted one (or more) of the columns to remain fixed when you scroll the other columns?

Over on the javatutorials portal Collin Fagan has posted an example that shows how to do just that. Check out Row Labels/Frozen Columns. (You'll have to scroll down through several posts to see it.)

Thanks Collin!

-- Sharon Zakhour

About

Blog about Java technology documentation and news about Java releases.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today