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

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
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