JavaFX#2 มาสร้าง JavaFX Application กันเถอะ
posted on 07 Jun 2009 23:25 by interviewz in JavaFX
Application ของเราในวันนี้ เราจะสร้าง ทรงกลม กับข้อความ (sphere and text)
ทรงกลมจะเปลี่ยนความทึบแสง (opacity) ตามช่วงเวลาที่ระบุ
และเรายังลากทรงกลมไปมาได้ด้วยเมาส์
Credit : เนื้อหาและรูปภาพทั้งหมด มาจาก JavaFX.com
แต่มันเป็น tutorial ภาษาอังกฤษ เราลองทำตามดูแล้ว ก็เลยเขียนเป็นภาษาไทยไว้
เผื่อคนอื่นสนใจ จะได้ง่ายขึ้นอีกนิดจ้า
1. สร้าง JavaFX Script Application project.
a. Choose File > New Project (Ctrl-Shift-N).
b. ในช่อง Project Name ตั้งชื่อว่า FirstJavaFXSphere
c. ในช่อง Project Location ใส่ที่ๆจะเก็บไฟล์โปรเจค
d. จากนั้นคลิก Finish จะปรากฏ Main.fx ในส่วนของ source editor ตามรูป
สังเกตว่าจะมีโค๊ดที่ Main.fx โดยอัตโนมัติ จะมีพวก import กับ object literals (เช่น Stage)
2. แก้ไขโค๊ด Stage object ตามตัวอย่างข้างล่าง เพื่อใส่ title ให้ window
และแก้ไข Scene object เพื่อระบุขนาดของ content area และ text ที่ต้องการให้ปรากฏในapplication
a. แก้ไข Stage and Scene object literals ให้เหมือนข้างล่าง เราสามารถ copy บรรทัดที่เป็นตัวหนาและ paste ลงไป สังเกตว่าพอวางลงไปแล้ว จะมี error flag ขึ้นมา โดยเราจะแก้ไข error นี้ในขั้นตอนต่อไป
Source Code
Stage {
title: "My First JavaFX Sphere"
scene: Scene {
width: 300
height: 300
content: [
Text {
font: Font { size: 22 }
x: 20, y: 90
textAlignment: TextAlignment.CENTER
content:"Welcome to \nJavaFX World"
} //Text
] // content
} // Scene
} // Stage
b.
คลิกขวาตรงไหนก็ได้ที่ว่างๆ แล้วเลือก Fix Imports
(Ctrl+Shift+I) เพื่อเอา error ออกไป
จะปรากฏ import
statement ดังข้างล่างนี้ ในส่วนบนสุดของ Main.fx file.
Source Code
import javafx.scene.text.TextAlignment;
3. ใส่ Circle object ที่เราจะทำให้มันเป็นทรงกลม โดยคลิกขยายส่วนของ Basic Shapes ที่อยู่ในหน้าต่าง Palette แล้วลาก Circle มาวางไว้ในบรรทัดที่อยู่บน Text code block ดังรูปที่แสดงข้างล่าง
4. แก้ไขค่าของตัวแปรต่างๆ เพื่อให้ใส่ข้อความลงไปได้ แล้วก็ใส่ RadialGradient เพิ่มลงไปเพื่อให้มีความลึก มันจะได้มีหน้าตาเหมือนรูปทรงกลมมากขึ้น
a. แก้ไขโค๊ดตามตัวอย่างที่เป็นตัวหนา
Source Code
Stage {
title: "My First JavaFX Sphere"
width: 300
height: 300
scene: Scene {
content: [
Circle {
centerX: 100,
centerY: 100
radius: 90
fill: RadialGradient {
centerX: 75
centerY: 75
radius: 90
proportional: false
stops: [
Stop {
offset: 0.0
color:
Color.web("#3B8DED")
},
Stop {
offset: 1.0
color:Color.web("#044EA4")
}
] // stops
} // RadialGradient
} // Circle
Text {
font: Font { size: 22 }
x: 20, y: 90
textAlignment: TextAlignment.CENTER
content:"Welcome to \nJavaFX World"
} //Text
] // content
} // Scene
} // Stage
b. คลิกขวาแล้วเลือก Fix Imports (Ctrl+Shift+I) จะปรากฏ import statement ดังข้างล่างนี้ ในส่วนบนสุดของ Main.fx file
Source Code
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;
5. Save (Ctrl+S) และดู Preview โดยคลิกปุ่ม Preview button ที่อยู่บน
toolbar.
จะมี Preview window ขึ้นมา
แสดงรูปวงกลมที่เราพึ่งปรับแต่งให้มันดูคล้ายทรงกลม
6. โดย default แล้วตัวหนังสือถูกกำหนดให้เป็นสีดำ เราสามารถเปลี่ยนเป็นสีขาวได้ ด้วยการแก้ไขสีตรงตัวแปร fill
Source Code
Text {
font: Font { size: 22 }
x: 20, y: 90
textAlignment: TextAlignment.CENTER
content:"Welcome to \nJavaFX World"
fill: Color.WHITE
}
7. เพิ่ม animation ที่จะเปลี่ยนค่า opacity ของทรงกลม
a. เพิ่มตัวแปร opacity และกำหนดค่าเริ่มต้นให้เป็น 1.0 ตัวแปรนี้จะถูกใช้ใน timeline ที่เราจำสร้างในขั้นตอนต่อไป
Source Code
var opacity = 1.0;
Stage {
title: "My First JavaFX Sphere"
width: 300
height: 300
b. เพิ่ม opacity instance variable เข้าไปใน Circle object และผูกมันเข้ากับ opacity global variable
Source Code
Circle {
centerX: 100, centerY: 100
radius: 90
opacity: bind opacity
fill: RadialGradient {
centerX: 75
centerY: 75
radius: 90
proportional: false
stops: [
Stop {
offset: 0.0
color: Color.web("#3B8DED")
},
Stop {
offset: 1.0
color:Color.web("#044EA4")
}
] // stops
} // RadialGradient
}
c. ขยายส่วนของ Animation ที่อยู่ในหน้าต่าง Palette ลาก Timeline มาไว้ตรงบรรทัดที่อยู่ก่อน Stage code block เหมือนในภาพ
การเคลื่อนไหวจะเกิดขึ้นตลอด timeline ซึ่งแสดงแทนด้วย javafx.animation.Timeline object
ทุก timeline จะมีอย่างน้อย 1 key frames ซึ่งแสดงแทนด้วยjavafx.animation.KeyFrame objects
d. เปลี่ยนค่าของตัวแปร time จาก 1s เป็น 5s
Source Code
Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames : [
KeyFrame {
time : 5s
canSkip: true
} // KeyFrame
] // keyFrames
} // Timeline
timeline จะวนซ้ำไปเรื่อยๆ รอบละ 5 วินาทีตามที่เรากำหนด
e. ลาก Animation > Values element จาก Palette มาไว้บนบรรทัดหลังตัวแปร time
Values จะเป็นการกำหนดตัวแปรที่จะให้มีการเปลี่ยนแปลงค่าไป ในแต่ละ key frame
f. copy บรรทัดตัวหนาข้างล่าง
Source Code
Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames : [
KeyFrame {
time : 5s
canSkip: true
values : [
opacity => 0.2 tween Interpolator.LINEAR
] // values
} // KeyFrame
] // keyFrames
} // Timeline
ค่าของ opacity จะถูกกำหนดภายในรอบ 5 วินาทีของ keyframe.
เครื่องหมาย => operator provides a literal constructor (a
special notation) that makes it easier to express the list of key interpolated
values or object properties.
เราใช้ tween operator เพื่อค่อยๆแก้ไขค่า opacity
ระหว่าง 1.0 ถึง 0.2
The Interpolator.LINEAR is the built-in interpolator instance that provides linear time interpolation.
g. เพิ่ม KeyFrame เข้าไปอีกอัน เพื่อเปลี่ยน opacity จาก 0.2 ถึง 1.0 ภายในรอบ 5 วินาทีต่อมา
Source Code
Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames : [
KeyFrame {
time : 5s
canSkip: true
values : [
opacity => 0.2 tween Interpolator.LINEAR
] // values
} // KeyFrame
KeyFrame {
time : 10s
canSkip: true
values : [
opacity => 1.0 tween Interpolator.LINEAR
] // values
} // KeyFrame
] // keyFrames
} // Timeline
h. เติม .play(); ต่อท้ายในส่วนที่ประกาศ Timeline object เหมือนที่แสดงเป็นตัวหนาข้างล่าง
play() method จะทำการเล่น timelineที่กำหนด
Source Code
Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames : [
KeyFrame {
time : 5s
canSkip : true
values : [
opacity => 0.2 tween Interpolator.LINEAR
]//values
}//KeyFrame
KeyFrame {
time : 10s
canSkip : true
values : [
opacity => 1.0 tween Interpolator.LINEAR
]//values
}//KeyFrame
]
}.play(); //Timeline
8. เพิ่มความสามารถในการเคลื่อนย้ายทรงกลมได้
โดยการคลิกเมาส์แล้วลาก
ตำแหน่งของ objects ใน application ถูกระบุโดยใช้ absolute coordinates.
เราจะแก้ไขโค๊ด
เพื่อให้ตำแหน่งของ object ขึ้นอยู่กับตำแหน่งของ
mouse pointer.
อย่าลืมว่าทรงกลมจะต้องถูกลากไปพร้อมกับ RadialGradient และตัวหนังสือ เมื่อเราต้องการให้หลายๆ object
มีพฤติกรรม/ความสามารถที่เหมือนๆกัน เราควรจะทำการรวมมันให้เป็นกลุ่มเดียวกัน (group)
a. สร้างตัวแปร x และ y กำหนดค่าเริ่มต้นให้เป็น 100.0 ตัวแปรนี้จะผูกตำแหน่งของวงกลมกับตำแหน่งของเมาส์
Source Code
var opacity = 1.0;
var x = 100.0;
var y = 100.0;
Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames: [
b.
ผูกตำแหน่งของ Circle object เข้ากับตัวแปร
x และ y ดังโค๊ดตัวอย่างด้านล่าง
นำ translateX และ translateY ไปแทนที่ centerX และ centerY ซึ่งจะกำหนด X และ
Y coordinates ของการเคลื่อนย้ายวงกลมไป
Source Code
scene: Scene {
content: [
Circle {
translateX: bind x
translateY: bind y
radius: 90
c. แก้ไข coordinates ของจุดศูนย์กลางของ RadialGradient To get a new value for the centerX coordinate, substract the current value of translateX, which is 100, from the initial value of centerX, which is 75. Thus you obtain -25. Perform a similar calculation for the centerY coordinate.
Source Code
fill: RadialGradient {
centerX: -25
centerY: -25
radius: 90
d. คลิกขวาตรงที่ว่างๆ แล้วเลือก Fix Imports (Ctrl+Shift+I) จะทำการ import javafx.transform.Translate
e. ลบตัวแปร x และ y ที่ระบุตำแหน่งของตัวหนังสือออก แล้วใส่ Translate transformation แล้วผูกตัวแปร x และ y เข้ากับตัวแปร x และ y ที่เป็น Global
Source Code
Text {
font: Font { size: 22 }
textAlignment: TextAlignment.CENTER
content:"Welcome to \nJavaFX World"
fill: Color.WHITE
transforms: [
Translate{
x: bind x - 76
y: bind y - 10
}
]
}
ลอง Preview ดูว่าแก้ไขไปแล้ว หน้าตาวงกลมและข้อความยังเหมือนเดิมรึป่าว
f. แก้ไข content เพิ่มทำการรวมกลุ่มของวงกลมและตัวหนังสือเข้าด้วยกัน
Source Code
scene: Scene {
width: 300
height: 300
content: Group {
content: [
Circle {
translateX: bind x
translateY: bind y
radius: 90
opacity: bind opacity
fill: RadialGradient {
centerX: -25
centerY: -25
radius: 90
proportional: false
stops: [
Stop {
offset: 0.0
color: Color.web("#3B8DED")
},
Stop {
offset: 1.0
color:Color.web("#044EA4")
}
] // stops
} // RadialGradient
}//Circle
Text {
font: Font { size: 22 }
textAlignment: TextAlignment.CENTER
content:"Welcome to \nJavaFX World"
fill: Color.WHITE
transforms: [
Translate{
x: bind x - 76
y: bind y - 10
}
]
} //Text
] // content
} //Group
} // Scene
g. คลิกขวาตรงที่ว่างๆแล้วเลือก Fix Imports (Ctrl+Shift+I) จะทำการ import javafx.scene.Group
h. ลาก Action > onMouseDragged จาก Palette มาไว้ก่อนเครื่องหมายปีกกาปิดของGroup object
i.Copy บรรทัดที่เป็นตัวหนาไปวาง เพื่อกำหนด function ที่จะถูกเรียกเมื่อเกิดเหตุการณ์ mouse-dragged event
Source Code
onMouseDragged: function( e: MouseEvent ):Void {
x = e.x;
y = e.y;
}
9. Save และ run the project.
a. ในหน้าต่าง project คลิกขวาที่ FirstJavaFXSphere project แล้วเลือก
Run Project.
Netbeans จะทำการ compile จะเตรียมไฟล์ที่จำเป็นในการรัน
application เมื่อcompiled สำเร็จ
จะปรากฏทรงกลมที่เปลี่ยน opacity
b. ลองลากทรงกลมด้วยเมาส์ สังเกตว่าเราสามารถลากทรงกลมออกนอกหน้าต่าง application ได้
ขั้นตอนต่อไป เราจะปรับปรุงให้มันลากออกไปนอกหน้าต่างแล้วหายไป
10. สร้างตัวแปรแบบ global ชื่อ X และ Y เพื่อจะนำไปใช้คำนวณ ในการควบคุมการลากทรงกลม
Source Code
var x = 100.0;
var y = 100.0;
var X;
var Y;
a. ลาก Action > onMousePressed จาก Palette ไปไว้ที่บรรทัดก่อน onMouseDragged function
b. Copy บรรทัดที่เป็นตัวหนาเพื่อกำหนด function ที่จะถูกเรียกเมื่อเกิดเหตุการณ์ mouse-pressed
Source Code
onMousePressed: function( e: MouseEvent ):Void {
X = e.sceneX - e.node.translateX;
Y = e.sceneY - e.node.translateY
}
c. Here e.sceneX หมายถึง X coordinate ของจุดที่เกิดเหตุการณ์เกี่ยวกับเมาส์
e.node.translateX หมายถึง X coordinate ของมุมซ้ายบนของ node เมื่อเกิดเหตุการณ์เกี่ยวกับเมาส์
d. Copy บรรทัดตัวหนาไปวางเพื่อแก้ไข onMouseDragged function.
Source Code
onMouseDragged: function( e: MouseEvent ):Void {
if (e.sceneX - X <0) {
e.node.translateX = 0;
} else { if (e.sceneX - X > 280 - e.node.boundsInLocal.width){
e.node.translateX = 280 - e.node.boundsInLocal.width;
} else {
e.node.translateX = e.sceneX - X;
}
}
if (e.sceneY - Y <0) {
e.node.translateY = 0;
} else {if (e.sceneY - Y > 280 - e.node.boundsInLocal.height){
e.node.translateY = 280 - e.node.boundsInLocal.height;
} else{
e.node.translateY = e.sceneY - Y;
}
}
}
11.Save the code and run the
project.
ตอนนี้ทรงกลมก็ไม่สามารถลากออกนอก scene ได้อีกต่อไป
สำเร็จแล้ว JavaFX
application ชิ้นแรกของเรา


#1 By Pygmii on 2009-06-08 01:48