2008年 12月 17日 水曜日
翻訳: コーヒーカップを JavaFX で。
JavaFX blog に出ていたコーヒーカップの作り方の翻訳です。
Scott Hommel の blog が原文になります。
かなり長いですが、とても面白い内容だと思うので、是非、読んでみてください。
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?
----------
JavaFX SDK 1.0 がリリースされました。JavaFX SDK のグラフィック機能を使ってちょっと遊んでみましょう。とてもきれいに作られているグラフィックは、簡単にプログラムできるのでしょうか?グラフィックの専門家だけがつくれるものなのか、誰でも簡単に学び、作成できるものなのでしょうか?
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.
-----------
私の経歴をちょっとご紹介すると、私は、テクニカルライターであり、多目的のコンピュータプログラマーです。が、ソフトウェアエンジニアでもなければ、グラフィックデザイナー、GUI の専門家というわけでもありません。なので、私は、JavaFX SDK を使って GUI を簡単に作ることができるか、ということを試す理想的な立場にいます。今回紹介している試みは、ある日の午後だけでできてしまうものでしたが、自分としては、とてもいい物ができました。すごい機能があるというわけではないですが、モダンな見かけで、陰影効果を用いた、SDK のデモで見たような 3D のグラフィックを作ることができました。
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.
------------
最初に私が行ったことは、GUI のチュートリアルを読んだことで、そのチュートリアルによって、基本的なことがすごいスピードで身に付きました。(JavaFX スクリプトを初めて使う人は、コアチュートリアルと同様、まずお読みになることをお勧めします)。次に、web サイトをのぞいて、一般的な、 3D を書く情報を探しました。
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:
--------------
探したなかで、inkscape という、ベクトルグラフィックスを描画するフリーウェアを使って、3D コーヒーカップを描く文章を見つけました。GUI 作成経験の少ない私でも、3D 描画を理解できる、まさに私が求めていた文章でした。inkscape には、2D のグラフィクスを元に、どうやって 3D に見える物体を作り出すかを、様々な色のグラデーションを使うことで表現する方法について説明されていました。なので、その説明を JavaFX API を使うことで実現してみようと思いました。午後の終わりには、かっこいいコーヒーカップを作り終えることができました。

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:
--------------
基本的なアプリケーションフレームワークを作るのは、とても簡単です。JavaFX テクノロジーは、複数のオブジェクトをグループとして、一緒にすることができるので、片方のグループをコーヒーソーサー、もう片方をカップとして作成しました。この2つのグループは、画面に表示されるグラフィカルオブジェクトを含んでいます。
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.
-------------
現段階では、なにも表示されません。ただ、コードは基本的な構造を実装してあり、これはとても重要なことです。各グループを、def を使って、変数に割り当てています。これは、もし片方のグループ (ソーサー) をもう片方のグループ (カップ) から、取り外したいようなことがあった場合に、簡単に行えるようにするためのものです
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):
---------------
コーヒーソーサー作成の最初の手順は、3色のグラデーション(RadialGradient) をもつ (Color.WHITESMOKE、 Color.LIGHTGRAY と Color.DARKGREY)、 Ellipse (楕円) を作成することです。

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.
------------------
translateX と translateY 変数からなるグループオブジェクトは、スクリーン上で、グループ全体を移動させたいときに便利です。 私の経験では、丁度よい位置を求めるためには、何度もやり直してみるしかないと思います。見栄えのよくなる設定はいくらでもあります。なので、一番適した場所を見つけるためには、別の値を設定し、コンパイルして実行してみるしかないと思います。
Next I added a dark gray ellipse below the plate, and another thin ellipse to make the lip (giving it a 3D feel):
------------------
次は、ソーサーの下にダークグレーの楕円を影として追加しました。また、もうひとつの細い楕円を、ふちとして追加しました (これが 3D 感を出してくれます)

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.
---------------------------
GUI オブジェクトはソースコードに出てきた順番で描画されるので、ソーサーをかたどるメインの楕円を一番最後におき、ほかのオブジェクト (ふちや、影) を覆い隠すようにしました。繰り返しますが、最適な位置の値は、何度か試してみて求めました。
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?
---------------------
カップの作成は、まず、ソーサーと同じようなグラデーションの円を作成します。私の方法では、まず、カップをまるで、粘土の丸いひとかたまりのようにしています。JavaFX API では、とても簡単に変形を行うことができるので、後で、この粘土をのばすして、カップの形にすることができます。すごいですね!

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:
-------------------
うまくいっているようです! ただ、カップが小さすぎるようです。なので、カップを「成長」させてみました。ただ、カップ全体の縮尺をかえる��けです。実際には、Y 座標を少し大きめに広げ、内側へつぶしたような、卵形のようになるようにしました。

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:
---------------
次に、カップに何か飲み物を注いでみましょう。内側のふちとコーヒーを表現する楕円の交わる部分を作成しました。ShapeIntersect クラスを使えば、これらのことは簡単にできます。

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:truestops: [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!
--------------------------
JavaFX 1.0 を使って GUI を作成しようという試みは、大成功だったと思うし、とても、楽しいかったです。宣言型のプログラミングは簡単に使えました。洗練されたビジュアルエフェクトを作ることも、全く大変ではなかったです。もっとも時間のかかった部分は、光をうまく表現するために、グラデーションの調整をしたところです。ただ、JavaFX の宣言型言語の本質は、プログラミングを簡単にしてくれるというところだと思います。JavaFX が、実際のグラフィックデザイナーが使ったときに、どんなものを作り出すのか楽しみで仕方がありません。
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
Posted at 09:33午後 12 17, 2008 by kenji in JavaFX の素人 |