JavaFX Basics (JavaFX အခြေခံများ)
IA (Internal Assessment) အတွက် tool တစ်ခုပါ၊ စာမေးပွဲ ခေါင်းစဉ် မဟုတ်ပါဘူး: JavaFX (Java နဲ့ desktop app တည်ဆောက်တဲ့ library) က စာမေးပွဲမှာ စစ်တဲ့ syllabus (IB သင်ရိုး) ထဲမှာ မပါလို့ သူ့ရဲ့ class (object တွေ ဖန်တီးဖို့ ပုံစံခွက်) တွေ၊ method (သီးခြား အလုပ်တစ်ခု လုပ်ပေးတဲ့ code အပိုင်း) တွေကို စာမေးပွဲမှာ မမေးပါဘူး။ JavaFX က window တွေ၊ button တွေ၊ text box တွေ ပါတဲ့ program တွေကို တည်ဆောက်ဖို့ toolkit (အသင့်ရေးထားတဲ့ Java class အစု) တစ်ခုပါ။ Internal Assessment (IB သင်တန်းမှာ ကျောင်းသားတစ်ယောက်ချင်း ကိုယ်တိုင် တည်ဆောက်ရပြီး ကျောင်းက ဆရာက အမှတ်ပေးတဲ့ အပိုင်း) အတွက် product (ကိုယ်တိုင် တည်ဆောက်ရတဲ့ program) ကို တည်ဆောက်တဲ့အခါ JavaFX ကို သုံးလို့ရပါတယ်။ Python နဲ့ ရေးနေသလား။ ဒီစာမျက်နှာရဲ့ tkinter version က tkinter Basics ပါ။
ခြုံငုံ မိတ်ဆက်
Internal Assessment မှာ ကိုယ်တိုင် ရွေးထားတဲ့ ပြဿနာ တစ်ခုကို ဖြေရှင်းပေးတဲ့ product တစ်ခုကို code ရေးပြီး တည်ဆောက်ရပါတယ်။ ပြီးရင် အဲဒီ product အလုပ်လုပ်ပုံကို video တိုလေး တစ်ခုနဲ့ ပြရပါတယ်။ Graphical user interface (GUI၊ window၊ button၊ text box တွေကို မြင်ရပြီး နှိပ်သုံးရတဲ့ user interface) ရှိရင် product ကို သုံးတဲ့သူတွေက terminal (စာသားပဲ ပြတဲ့ window) ထဲမှာ command တွေ ရိုက်ထည့်စရာ မလိုဘဲ button တွေကို နှိပ်ပြီး box တွေထဲမှာ စာရိုက်ထည့်လို့ ရပါတယ်။
JavaFX က Java အတွက် GUI framework တစ်ခုပါ: window တွေ၊ button တွေ၊ text box တွေနဲ့ layout (အဲဒီ အစိတ်အပိုင်းတွေကို screen ပေါ်မှာ စီစဉ်ထားပုံ) တွေအတွက် အသင့်ရေးထားတဲ့ class အစု တစ်ခုပါ။ JavaFX ကို များသောအားဖြင့် Java နဲ့ သီးခြား download လုပ်ရပါတယ်: SDK (software development kit: ကိုယ့် project ထဲ ထည့်ရတဲ့ library file တွေ ပါတဲ့ folder) အဖြစ် download လုပ်တာ၊ ဒါမှမဟုတ် build tool (ကိုယ့် project လိုအပ်တဲ့ library တွေကို download လုပ်ပေးတဲ့ program) ကနေတစ်ဆင့် ယူတာ လုပ်ပါတယ်။ ဒီစာမျက်နှာမှာ အလုပ်လုပ်တဲ့ interface တစ်ခု စတင် တည်ဆောက်ဖို့ လိုတဲ့ အခြေခံတွေကို လေ့လာပါမယ်: window တွေ၊ control (button၊ text field စတဲ့ user သုံးတဲ့ အစိတ်အပိုင်း) တွေနဲ့ event handling (user က နှိပ်တာ ဒါမှမဟုတ် စာရိုက်တာကို program က တုံ့ပြန်အောင် လုပ်ခြင်း) ပါ။ နောက်ပိုင်း စာမျက်နှာတွေမှာ MVC architecture (MVC: app ကို Model၊ View၊ Controller ဆိုပြီး အပိုင်းသုံးပိုင်း ခွဲရေးတဲ့ ပုံစံ)၊ FXML and controllers (screen ပုံစံကို FXML file ထဲမှာ ရေးပြီး controller class နဲ့ ချိတ်ခြင်း) နဲ့ file persistence (program ပိတ်သွားပြီးနောက်မှာလည်း ဒေတာ ဆက်ရှိနေအောင် သိမ်းထားခြင်း) ကို လေ့လာပါမယ်။
ရည်မှန်းချက်: ဒီစာမျက်နှာ ပြီးတဲ့အခါ user ရဲ့ လုပ်ဆောင်ချက်တွေကို တုံ့ပြန်တဲ့ control တွေ ပါတဲ့ window တစ်ခုကို ဖန်တီးနိုင်ရပါမယ်။
အဓိက အယူအဆများ
JavaFX ရဲ့ ဖွဲ့စည်းပုံ
JavaFX window တစ်ခုကို အလွှာ သုံးလွှာနဲ့ တည်ဆောက်ပါတယ်:
| အလွှာ | Class | ဘာလဲ |
|---|---|---|
| Stage | Stage | Window ကိုယ်တိုင်ပါ |
| Scene | Scene | Window ထဲမှာ ပြတဲ့ အရာ အားလုံးပါ: screen တစ်ခုစာ content |
| Nodes | Button, Label, TextField စတာတွေ | Scene ကို ဖွဲ့စည်းထားတဲ့ control တွေနဲ့ layout container တွေပါ |
Stage တစ်ခုက တစ်ကြိမ်မှာ Scene တစ်ခုကိုပဲ ပြပါတယ်။ Scene တစ်ခုက root node (အပေါ်ဆုံး node၊ များသောအားဖြင့် layout container တစ်ခု) တစ်ခုကို ကိုင်ထားပြီး root က တခြား node (scene ထဲမှာ ပါတဲ့ အစိတ်အပိုင်း) တွေကို ကိုင်ထားပါတယ်: control တွေ (button တွေ၊ label တွေလို user မြင်ပြီး သုံးတဲ့ အစိတ်အပိုင်းတွေ) နဲ့ နောက်ထပ် layout container တွေ (တခြား node တွေကို ကိုင်ထားပြီး screen ပေါ်မှာ စီစဉ်ပေးတဲ့ node တွေ) ပါ။ Node တွေ အားလုံး ပေါင်းပြီး tree (သစ်ပင်လို အဆင့်ဆင့် ခွဲထွက်တဲ့ ဖွဲ့စည်းပုံ) တစ်ခု ဖြစ်ပါတယ်၊ ဒါကို scene graph လို့ ခေါ်ပါတယ်။ Screen တစ်ခု ပြောင်းပြချင်ရင် stage ပေါ်က scene ကို လဲလို့ ရပါတယ်။
Application Lifecycle (app စတင်ချိန်ကနေ ပြီးဆုံးချိန်အထိ ဖြစ်စဉ်)
JavaFX app တစ်ခုက Application ကို extend လုပ်တဲ့ class တစ်ခုပါ (JavaFX ရဲ့ ကိုယ်ပိုင် Application class ပေါ်မှာ အခြေခံ တည်ဆောက်ပါတယ်)။ ပြီးတော့ start method ကို override လုပ်ပါတယ် (အဲဒီ method ရဲ့ ကိုယ်ပိုင် version ကို ရေးပါတယ်):
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class HelloApp extends Application {
@Override
public void start(Stage stage) {
Label greeting = new Label("Hello, JavaFX!");
StackPane root = new StackPane(greeting);
Scene scene = new Scene(root, 400, 300);
stage.setTitle("My First App");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
ဒီ code ကို run တဲ့အခါ ဖြစ်တာတွေ:
launch()က JavaFX runtime (window တွေကို run ပေးပြီး click တွေကို တုံ့ပြန်ပေးတဲ့ JavaFX ရဲ့ အစိတ်အပိုင်း) ကို စတင်ပြီးHelloAppobject တစ်ခုကို ဖန်တီးကာ အဲဒီ object ရဲ့start()method ကို ခေါ်ပါတယ်start()က primaryStage(အဓိက window) ကို လက်ခံရပါတယ်- Code က control တစ်ခုကို ဖန်တီးပြီး layout တစ်ခုထဲ ထည့်ကာ အဲဒီ layout ကို
Sceneတစ်ခုထဲ ထည့်ပါတယ် - Scene ကို stage ပေါ်မှာ သတ်မှတ်ပြီး
show()ကို ခေါ်ပါတယ်။show()က window ကို ပေါ်လာစေပါတယ်
start() ကို ကိုယ်တိုင် မခေါ်ပါနဲ့: launch() က ကိုယ့်အစား ခေါ်ပေးပါတယ်။
Example တွေကို run ခြင်း။ Java install လုပ်ထားတာ တော်တော်များများမှာ JavaFX မပါပါဘူး။ ဒါကြောင့် JavaFX library ကို ကိုယ့် IDE (code ရေးပြီး run ဖို့ သုံးတဲ့ software) ဒါမှမဟုတ် build tool ထဲက project မှာ ထည့်ရပါတယ်။ IDE တစ်ခုစီမှာ ဒီအတွက် ကိုယ်ပိုင် setting ရှိပါတယ်။ ဒါ မလုပ်ရင် window မပွင့်ခင်မှာပဲ program က JavaFX runtime components are missing (JavaFX runtime အစိတ်အပိုင်းတွေ မရှိပါ) လို error တစ်ခုနဲ့ ရပ်သွားပါတယ်။
အသုံးများတဲ့ Control များ
အောက်က အပိုင်းတွေထဲက snippet (code အပိုင်းအစ) တိုလေး တစ်ခုစီက start() ထဲက line အနည်းငယ်ပဲ ပါတဲ့ သီးခြား ဥပမာ တစ်ခုစီပါ။ လိုက်ကြည့်ရ လွယ်အောင် snippet တွေမှာ nameField၊ addBtn၊ result လို နာမည်တွေကို ထပ်ခါ သုံးထားပေမဲ့ program တစ်ခုတည်း မဟုတ်ပါဘူး: တွဲပြီး paste လုပ်ရင် variable (တန်ဖိုး သိမ်းထားတဲ့ နာမည်ပေးထားတဲ့ နေရာ) တချို့ကို နှစ်ခါ ကြေညာမိမယ်၊ control တစ်ခုတည်းကို layout တစ်ခုထက် ပိုပြီး ထည့်မိပါလိမ့်မယ်။ JavaFX မှာ control တစ်ခုကို တစ်ကြိမ်မှာ layout တစ်ခုထဲမှာပဲ ထားခွင့် ရှိပါတယ်။ deleteBtn နဲ့ clearBtn ဆိုတဲ့ button တွေက addBtn လိုပဲ ဖန်တီးထားတဲ့ button တွေလို့ ယူဆပါ။ အားလုံးကို ပေါင်းစပ်ခြင်း အောက်က program အပြည့်အစုံက ဒီအပိုင်းတွေ အလုပ်လုပ်တဲ့ app တစ်ခုထဲမှာ ဘယ်လို ပေါင်းစပ်သွားလဲ ပြပါတယ်။ အဲဒီ program မှာ သုံးတဲ့ JavaFX class တစ်ခုစီအတွက် file ရဲ့ ထိပ်ဆုံးမှာ import line တစ်ကြောင်းစီ ပါပါတယ် (ဥပမာ import javafx.scene.control.Label;)။
Label (စာသား ပြတဲ့ control)
User ဖတ်လို့ ရပေမဲ့ ပြင်လို့ မရတဲ့ စာသားကို ပြပါတယ်။ ခေါင်းစဉ်တွေ၊ ညွှန်ကြားချက်တွေ ဒါမှမဟုတ် ရလဒ်တွေ ပြဖို့ label တွေကို သုံးပါ။
Label title = new Label("Student Manager");
Label result = new Label(""); // empty for now, updated later
result.setText("Found 3 students"); // update the text
TextField (စာ တစ်ကြောင်း ရိုက်ထည့်တဲ့ box)
User စာရိုက်ထည့်တဲ့ line တစ်ကြောင်းတည်း ရှိတဲ့ box ပါ။ User ရိုက်ထည့်ထားတာကို ဖတ်ဖို့ getText() ကို သုံးပြီး box ကို ရှင်းဖို့ clear() ကို သုံးပါ။
TextField nameField = new TextField();
nameField.setPromptText("Enter student name"); // placeholder text
String name = nameField.getText(); // read the input
nameField.clear(); // clear after use
Button (နှိပ်လို့ရတဲ့ ခလုတ်)
User နှိပ်တဲ့ button ပါ။ နှိပ်တိုင်း run ရမယ့် code ကို button ကို ပေးဖို့ setOnAction() ကို သုံးပါ (ဒါက button ရဲ့ event handler ပါ၊ အောက်က Event Handling အပိုင်းမှာ ရှင်းပြထားပါတယ်)။
Button addBtn = new Button("Add Student");
addBtn.setOnAction(event -> {
String name = nameField.getText();
result.setText("Added: " + name);
nameField.clear();
});
TextArea (စာ line အများကြီး ရိုက်ထည့်တဲ့ box)
စာ အရှည်တွေ ရိုက်ထည့်ဖို့ ဒါမှမဟုတ် output (program က ထုတ်ပြတဲ့ ရလဒ်) ကို ပြဖို့ line အများကြီး ပါတဲ့ text box ပါ။
TextArea outputArea = new TextArea();
outputArea.setEditable(false); // read-only display
outputArea.setPrefRowCount(10);
outputArea.appendText("Line 1\n");
outputArea.appendText("Line 2\n");
ComboBox (ရွေးချယ်စရာ စာရင်း)
Drop-down list (နှိပ်လိုက်ရင် အောက်ကို ကျလာတဲ့ ရွေးချယ်စရာ စာရင်း) ပါ: user က ဖွင့်ပြီး option တစ်ခုကို ရွေးပါတယ်။
ComboBox<String> gradeBox = new ComboBox<>();
gradeBox.getItems().addAll("Grade 11", "Grade 12");
gradeBox.setValue("Grade 11"); // default selection
String selected = gradeBox.getValue(); // read selection
CheckBox (အမှန်ခြစ် အကွက်)
ဟုတ်/မဟုတ် ရွေးချယ်မှုအတွက် user က ခြစ်လို့ ဒါမှမဟုတ် ခြစ်ထားတာကို ဖြုတ်လို့ ရတဲ့ box ပါ။ ခြစ်ထားရင် isSelected() က true ကို return (ရလဒ်အဖြစ် ပြန်ပေး) လုပ်ပါတယ်။
CheckBox hlBox = new CheckBox("HL Student");
boolean isHL = hlBox.isSelected(); // true or false
Layout Container များ
Control တွေကို layout container (layout pane လို့လည်း ခေါ်ပါတယ်) တွေထဲမှာ ထည့်ပါတယ်။ Layout container က control တစ်ခုစီ screen ပေါ်မှာ ဘယ်နေရာမှာ ပေါ်မလဲ ဆုံးဖြတ်ပေးပါတယ်။ Container တစ်ခုက တခြား container တွေကိုလည်း ကိုင်ထားနိုင်ပါတယ်။
VBox: ဒေါင်လိုက် စီခြင်း
သူ ကိုင်ထားတဲ့ node တွေ (သူ့ရဲ့ children) ကို အပေါ်ကနေ အောက်ကို စီပေးပါတယ်။ သူတို့ကြားမှာ နေရာလွတ် ထည့်ချင်ရင် ထည့်လို့ ရပါတယ်။
VBox form = new VBox(10); // 10px spacing between children
form.setPadding(new Insets(20));
form.getChildren().addAll(nameField, gradeBox, addBtn, result);
HBox: အလျားလိုက် တန်းစီခြင်း
သူ့ children တွေကို ဘယ်ကနေ ညာကို စီပေးပါတယ်။
HBox buttonRow = new HBox(10);
buttonRow.getChildren().addAll(addBtn, deleteBtn, clearBtn);
BorderPane: အပိုင်း ငါးပိုင်း
သူ့ နေရာကို အပိုင်း ငါးပိုင်း ခွဲပါတယ်: top (အပေါ်)၊ bottom (အောက်)၊ left (ဘယ်)၊ right (ညာ) နဲ့ centre (အလယ်)။ ပုံမှန် app screen တစ်ခုနဲ့ ကိုက်ပါတယ်: အပေါ်မှာ ခေါင်းစဉ်၊ အလယ်မှာ အဓိက content၊ အောက်ခြေမှာ button တွေ။
BorderPane layout = new BorderPane();
layout.setTop(title);
layout.setCenter(outputArea);
layout.setBottom(buttonRow);
GridPane: Row/Column ဇယားကွက်
Control တစ်ခုစီကို column (ဒေါင်လိုက် ကော်လံ) နဲ့ row (အလျားလိုက် အတန်း) နေရာ တစ်ခုမှာ ချပါတယ်၊ ဇယား တစ်ခုရဲ့ cell (ဇယားကွက်ထဲက အကွက်) တွေလိုပါပဲ။ Label တွေနဲ့ box တွေ column လိုက် တန်းစီရတဲ့ form (ဒေတာ ဖြည့်ရတဲ့ အကွက်တွေ ပါတဲ့ အပိုင်း) တွေနဲ့ ကိုက်ပါတယ်။ add က row မတိုင်ခင် column ကို အရင် ယူတာကို သတိပြုပါ။
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(20));
grid.add(new Label("Name:"), 0, 0); // column 0, row 0
grid.add(nameField, 1, 0); // column 1, row 0
grid.add(new Label("Grade:"), 0, 1); // column 0, row 1
grid.add(gradeBox, 1, 1); // column 1, row 1
အလုပ်ဖြစ်တဲ့ အရိုးရှင်းဆုံး layout ကို ရွေးပါ။ Region တွေထဲမှာ VBox ဒါမှမဟုတ် HBox ပါတဲ့ BorderPane တစ်ခုက screen တော်တော်များများအတွက် လုံလောက်ပါတယ်။ Layout အမျိုးအစား အားလုံးကို သုံးဖို့ မလိုပါဘူး။
Event Handling (user ရဲ့ လုပ်ဆောင်ချက်ကို တုံ့ပြန်ခြင်း)
Event (ဖြစ်ရပ်) ဆိုတာ program က တုံ့ပြန်နိုင်တဲ့ အရာ တစ်ခုပါ။ များသောအားဖြင့် button ကို နှိပ်တာ၊ Enter ကို နှိပ်တာ ဒါမှမဟုတ် list ထဲက item တစ်ခုကို ရွေးတာလို user ရဲ့ လုပ်ဆောင်ချက် တစ်ခုပါ။ Event တစ်ခုကို တုံ့ပြန်တဲ့ code ကို အဲဒီ event ရဲ့ event handler လို့ ခေါ်ပါတယ်။ GUI program တစ်ခုက event-driven (event တွေ ဖြစ်မှ code run တဲ့) program ပါ: start() က window ကို တည်ဆောက်ပြီးတာနဲ့ program က စောင့်နေပြီး event handler တစ်ခုစီက သူ့ event ဖြစ်တဲ့အခါ run ပါတယ်။ User နှိပ်တဲ့ အစဉ်က ကိုယ့် code run မယ့် အစဉ်ကို ဆုံးဖြတ်ပါတယ်။
Lambda Syntax (lambda ရေးပုံ)
Handler ကို များသောအားဖြင့် lambda expression (နာမည် မပါတဲ့ method တစ်ခုကို အတိုချုပ် ရေးတဲ့ နည်း) နဲ့ ချိတ်ပါတယ်။ event -> { ... } မှာ တွန့်ကွင်း { } ကြားက code က event ဖြစ်တဲ့အခါ JavaFX run ပေးမယ့် code ဖြစ်ပြီး event ကတော့ ဘာဖြစ်ခဲ့လဲ ဖော်ပြတဲ့၊ JavaFX က ပေးလိုက်တဲ့ object တစ်ခုပါ။
addBtn.setOnAction(event -> {
// code that runs when button is clicked
String name = nameField.getText();
if (!name.isEmpty()) {
result.setText("Added: " + name);
nameField.clear();
}
});
Lambda တွေက syllabus မှာ စစ်တဲ့ Java ထဲမှာ မပါပါဘူး။ JavaFX code မှာတော့ handler ကို ချိတ်တဲ့ ပုံမှန် နည်းလမ်းပါ။ FXML and Controllers စာမျက်နှာက နောက်ထပ် နည်းလမ်းကို ပြပါတယ်: FXML layout file (screen ပုံစံကို ဖော်ပြတဲ့ file) က button နဲ့ ချိတ်ပေးတဲ့ နာမည်ပါတဲ့ method တစ်ခုပါ။
TextField မှာ Enter Key ကို ကိုင်တွယ်ခြင်း
Text field ထဲမှာ Enter ကို နှိပ်ရင် အဲဒီ text field ရဲ့ ကိုယ်ပိုင် setOnAction နဲ့ သတ်မှတ်ထားတဲ့ handler run ပါတယ်။ ဒီမှာ handler က addBtn.fire() ကို ခေါ်ပါတယ်။ addBtn.fire() က button ကို နှိပ်လိုက်သလိုပဲ Add button ရဲ့ handler ကို run ပေးပါတယ်။
nameField.setOnAction(event -> {
// runs when user presses Enter in the text field
addBtn.fire(); // trigger the button's action
});
ComboBox ရွေးချယ်မှု ပြောင်းခြင်း
ComboBox က သူ့ value ပြောင်းတိုင်း (ဥပမာ user က တခြား item တစ်ခုကို ရွေးလိုက်တဲ့အခါ) သူ့ setOnAction နဲ့ သတ်မှတ်ထားတဲ့ handler ကို run ပါတယ်။ ဒါကြောင့် ဒီ handler က ရွေးပြီးတာနဲ့ ချက်ချင်း run ပါတယ်။
gradeBox.setOnAction(event -> {
String grade = gradeBox.getValue();
result.setText("Selected: " + grade);
});
Event handler တွေကို တိုတို ထားပါ။ Handler တစ်ခုက line အနည်းငယ်ထက် ရှည်လာရင် အဲဒီ အလုပ်ကို သီးခြား method တစ်ခုထဲ ရွှေ့ပြီး handler ကနေ အဲဒီ method ကို ခေါ်ပါ။ အောက်က program အပြည့်အစုံမှာ refreshDisplay() နဲ့ ဒီလို လုပ်ထားပါတယ်။ တိုတဲ့ handler တွေက ဖတ်ရတာ၊ ပြင်ရတာ ပိုလွယ်ပါတယ်။
Alert နဲ့ Dialog များ
Alert ဆိုတာ message တစ်ခုကို ပြတာ၊ user ကို တစ်ခုခု အတည်ပြုခိုင်းတာ ဒါမှမဟုတ် error ကို အသိပေးတာ လုပ်တဲ့ pop-up (ရုတ်တရက် ပေါ်လာတဲ့) window အသေးလေး တစ်ခုပါ။ showAndWait() က alert ကို ပြပြီး user က ပိတ်လိုက်တဲ့အထိ ကိုယ့် code ကို ခဏ ရပ်ထားပါတယ်။
Information Alert (သတင်း အသိပေးတဲ့ alert)
Alert info = new Alert(Alert.AlertType.INFORMATION);
info.setTitle("Success");
info.setHeaderText(null);
info.setContentText("Student added successfully.");
info.showAndWait();
Confirmation Alert (အတည်ပြုချက် တောင်းတဲ့ alert)
Confirmation alert မှာ OK နဲ့ Cancel button တွေ ပါပြီး user က ဘယ်တစ်ခုကို နှိပ်လဲဆိုတာ showAndWait() က ကိုယ့် code ကို ပြောပြပါတယ်:
Alert confirm = new Alert(Alert.AlertType.CONFIRMATION);
confirm.setTitle("Confirm Delete");
confirm.setHeaderText(null);
confirm.setContentText("Delete this student? This cannot be undone.");
if (confirm.showAndWait().get() == ButtonType.OK) {
// the user clicked OK, so delete the student here
}
showAndWait() က user နှိပ်လိုက်တဲ့ button ကို return ပြန်ပေးပါတယ်။ .get() က အဲဒီ button ကို ရလဒ်ထဲကနေ ထုတ်ယူပေးလို့ ButtonType.OK နဲ့ နှိုင်းယှဉ်လို့ ရပါတယ်။ Alert ကို သူ့ window ရဲ့ close button နဲ့ ပိတ်ရင် Cancel ကို နှိပ်တာနဲ့ အတူတူပါပဲ။
Error Alert (error ပြတဲ့ alert)
Alert error = new Alert(Alert.AlertType.ERROR);
error.setTitle("Error");
error.setHeaderText(null);
error.setContentText("Name field cannot be empty.");
error.showAndWait();
Alert တွေကို လိုမှသာ သုံးပါ။ User ထည့်လိုက်တဲ့ input (program ထဲ ထည့်ပေးတဲ့ ဒေတာ) ကို ပြင်ဖို့ လိုတဲ့အခါ (ဥပမာ “name is required”၊ နာမည် ထည့်ဖို့ လိုပါတယ်) pop-up ထက် label ထဲက message က များသောအားဖြင့် ပိုကောင်းပါတယ်။ Alert တွေကို အတည်ပြုချက် တောင်းတာတွေနဲ့ user မလွတ်သွားရမယ့် အရေးကြီးတဲ့ error တွေအတွက်ပဲ ထားပါ။
အားလုံးကို ပေါင်းစပ်ခြင်း
ဒါက user ကို list ထဲ နာမည်တွေ ထည့်ပြီး screen ပေါ်မှာ list ကို ကြည့်ခွင့်ပေးတဲ့ application အသေးလေး အပြည့်အစုံ တစ်ခုပါ။
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.ArrayList;
public class NameListApp extends Application {
private ArrayList<String> names = new ArrayList<>();
private TextArea display = new TextArea();
@Override
public void start(Stage stage) {
Label title = new Label("Name List Manager");
TextField nameField = new TextField();
nameField.setPromptText("Enter a name");
Button addBtn = new Button("Add");
Button clearBtn = new Button("Clear All");
Label status = new Label("");
addBtn.setOnAction(event -> {
String name = nameField.getText().trim();
if (name.isEmpty()) {
status.setText("Please enter a name.");
} else {
names.add(name);
nameField.clear();
status.setText("Added: " + name);
refreshDisplay();
}
});
nameField.setOnAction(event -> addBtn.fire());
clearBtn.setOnAction(event -> {
Alert confirm = new Alert(Alert.AlertType.CONFIRMATION);
confirm.setTitle("Confirm");
confirm.setHeaderText(null);
confirm.setContentText("Clear all names?");
if (confirm.showAndWait().get() == ButtonType.OK) {
names.clear();
status.setText("List cleared.");
refreshDisplay();
}
});
display.setEditable(false);
display.setPrefRowCount(10);
HBox buttons = new HBox(10, addBtn, clearBtn);
VBox form = new VBox(10, nameField, buttons, status);
form.setPadding(new Insets(10));
BorderPane root = new BorderPane();
root.setTop(title);
root.setCenter(display);
root.setBottom(form);
root.setPadding(new Insets(10));
Scene scene = new Scene(root, 400, 400);
stage.setTitle("Name List Manager");
stage.setScene(scene);
stage.show();
}
private void refreshDisplay() {
display.clear();
for (int i = 0; i < names.size(); i++) {
display.appendText((i + 1) + ". " + names.get(i) + "\n");
}
}
public static void main(String[] args) {
launch(args);
}
}
ဒီ program က ပြသတဲ့ အချက်များ:
BorderPanelayout ပါတဲ့ stage နဲ့ scene တစ်ခု- Prompt text (box အလွတ် ဖြစ်နေချိန်မှာ ပြတဲ့ မီးခိုးရောင် အရိပ်အမြွက် စာ) ပါတဲ့ input အတွက်
TextFieldတစ်ခု - Event handler တွေက lambda တွေ ဖြစ်တဲ့ button တွေ
- ဖတ်ရုံသာ ရတဲ့ display (ဒေတာ ပြတဲ့ နေရာ) အဖြစ် သုံးထားတဲ့
TextArea - နာမည် အားလုံးကို မဖျက်ခင် user ကို အတည်ပြုခိုင်းတဲ့
Alert - ဒေတာကို သိမ်းဖို့
ArrayList(ကြီးလာ၊ သေးသွားနိုင်တဲ့ list) တစ်ခု (window ပိတ်သွားရင် နာမည်တွေ ပျောက်သွားပါတယ်။ နာမည်တွေကို file ထဲ သိမ်းပြီး ပြန် load လုပ်ပုံကို File I/O in Apps မှာ ပြထားပါတယ်) - Display ကို update လုပ်ပေးပြီး handler နှစ်ခုလုံးက ခေါ်သုံးတဲ့ သီးခြား method
refreshDisplay()
IA Project တွေမှာ အသုံးများတဲ့ ပုံစံများ
Input Validation (ထည့်ပေးတဲ့ ဒေတာ မှန်မမှန် စစ်ခြင်း)
Input validation ဆိုတာ user ထည့်လိုက်တဲ့ input ကို မသုံးခင် စစ်တာပါ။ Program အပြည့်အစုံထဲက Add handler ရဲ့ ဒီ version မှာ အရှည်ကို စစ်တဲ့ အဆင့် တစ်ခု ထပ်ထည့်ထားပါတယ်:
addBtn.setOnAction(event -> {
String name = nameField.getText().trim();
if (name.isEmpty()) {
status.setText("Error: Name cannot be empty.");
} else if (name.length() > 50) {
status.setText("Error: Name too long (max 50 characters).");
} else {
// the input is valid, so add the name
names.add(name);
nameField.clear();
status.setText("Added: " + name);
refreshDisplay();
}
});
ရိုက်ထည့်တဲ့ စာသားက ဂဏန်း ဟုတ်မဟုတ် စစ်ဖို့ try block ထဲမှာ Integer.parseInt ဒါမှမဟုတ် Double.parseDouble နဲ့ ပြောင်းပါ။ စာသားက ဂဏန်း မဟုတ်ရင် ပြောင်းတဲ့အခါ NumberFormatException ကို throw (exception ဖြစ်ကြောင်း အချက်ပြ) လုပ်ပါတယ်။ Exception Handling စာမျက်နှာမှာလို ကိုယ့် catch block က message တစ်ခု ပြပြီး အဲဒီ exception (program run နေစဉ် ဖြစ်တဲ့ အမှား) ကို ကိုင်တွယ်နိုင်ပါတယ်။
Control တွေကို Disable လုပ်ခြင်း
Button ရဲ့ လုပ်ဆောင်ချက်က အဓိပ္ပာယ် မရှိတဲ့ အချိန်မှာ အဲဒီ button ကို disable (မီးခိုးရောင် ဖြစ်သွားပြီး နှိပ်လို့ မရအောင်) လုပ်ထားနိုင်ပါတယ်။ ဥပမာ name field အလွတ် ဖြစ်နေချိန်မှာ Add button ပါ:
addBtn.setDisable(true); // greyed out until a name is typed
// runs every time the text in nameField changes
nameField.textProperty().addListener(
(obs, oldText, newText) -> addBtn.setDisable(newText.trim().isEmpty())
);
Listener ဆိုတာ value တစ်ခု ပြောင်းတိုင်း JavaFX run ပေးတဲ့ code ပါ။ ဒီမှာတော့ nameField ထဲက စာသားပါ။ ဒီ listener က parameter (method ကို ပေးလိုက်တဲ့ တန်ဖိုးကို လက်ခံတဲ့ variable) သုံးခု ပါတဲ့ lambda တစ်ခုပါ: ပြောင်းသွားတဲ့ property (object တစ်ခုရဲ့ စာသား၊ အရွယ်အစား စတဲ့ နာမည်ပေးထားတဲ့ တန်ဖိုး) (obs)၊ စာသား အဟောင်းနဲ့ စာသား အသစ်ကို JavaFX က listener ကို ပေးပါတယ်။
Status Label ကို Update လုပ်ခြင်း
Form ရဲ့ အောက်ခြေက status label (အခြေအနေ ပြတဲ့ label) က pop-up မသုံးဘဲ ဘာဖြစ်သွားလဲ ဆိုတာကို user ကို ပြောပြပါတယ်:
status.setText("Ready"); // default state
status.setText("Added: " + name); // after successful action
status.setText("Error: invalid input"); // on validation failure
Quick Check (အမြန် စစ်ဆေးမေးခွန်း)
Q1. JavaFX မှာ application window ကို ဘယ် class က ကိုယ်စားပြုသလဲ။
Q2. ပထမ window ကို တည်ဆောက်ပြီး ပြတဲ့ JavaFX ရဲ့ အဓိက entry point (program စ run တဲ့ နေရာ) က ဘယ် method လဲ။
Q3. User က TextField ထဲမှာ ရိုက်ထည့်ထားတဲ့ စာသားကို ဘယ်လို ဖတ်သလဲ။
Q4. ဘယ် layout container က သူ့ children တွေကို ဒေါင်လိုက် စီပေးသလဲ။
Q5. Alert တစ်ခုကို ပြပြီး user တုံ့ပြန်တာကို စောင့်ပေးတဲ့ method က ဘယ်ဟာလဲ။
Code Completion (code ကွက်လပ် ဖြည့်ခြင်း)
ဒီ JavaFX application ထဲက ပျောက်နေတဲ့ အပိုင်းတွေကို ဖြည့်ပါ။
ကွက်လပ် ဖြည့်ပါ: Button ကို နှိပ်တဲ့အခါ စကားလုံး တစ်လုံးမှာ character (စာလုံး ဒါမှမဟုတ် သင်္ကေတ) ဘယ်နှစ်လုံး ပါလဲ ပြပေးတဲ့ ဒီ JavaFX application ကို ပြည့်စုံအောင် ဖြည့်ပါ။
public class LetterCountApp extends {
@Override
public void start( stage) {
TextField wordField = new TextField();
Label output = new Label("");
Button countBtn = new Button("Count");
countBtn.setOnAction(event -> {
String word = wordField.;
output.setText(word + " has " + word.length() + " characters");
});
VBox root = new VBox(10, wordField, countBtn, output);
Scene scene = new (root, 300, 200);
stage.setScene(scene);
stage.;
}
} Spot the Error (အမှား ရှာခြင်း)
ဒီ JavaFX code က window တစ်ခုကို ပြရမှာပါ၊ ဒါပေမဲ့ run တဲ့အခါ ဘာမှ မပေါ်လာပါဘူး။
Bug Hunt (အမှား ရှာပါ): Application က error မရှိဘဲ run ပေမဲ့ window မပေါ်လာပါဘူး။ ကျန်နေတဲ့ အဆင့်ကို ရှာပါ။
Line 7 က "window should appear here" (window ဒီနေရာမှာ ပေါ်လာရမယ်) လို့ ရေးထားတဲ့ comment ပါ။
Line 7 အတွက် မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:
Predict the Output (output ကို ကြိုခန့်မှန်းခြင်း)
ကြိုခန့်မှန်းပါ: User က nameField ထဲမှာ "Alice" လို့ ရိုက်ထည့်ပြီး button ကို နှိပ်ပါတယ်။ result label က ဘယ်စာသားကို ပြမလဲ။
Button btn = new Button("Greet");
Label result = new Label("");
btn.setOnAction(event -> {
String name = nameField.getText();
result.setText("Hello, " + name + "!");
nameField.clear();
}); Practice Exercises (လေ့ကျင့်ခန်းများ)
(4 marks) စတာတွေက လေ့ကျင့်ခန်း တစ်ခုချင်းစီအတွက် ရနိုင်တဲ့ အမှတ်ပါ။ IB စာမေးပွဲ မေးခွန်းတွေမှာ အမှတ်ကို ဒီလို ပြလေ့ ရှိပါတယ်။
Core (အခြေခံ အဆင့်)
-
နာမည်ကတ် App (4 marks):
TextFieldတစ်ခု၊ “Make Tag” လို့ စာတန်း ပါတဲ့Buttonတစ်ခုနဲ့Labelတစ်ခု ပါတဲ့ JavaFX application တစ်ခုကို Construct (ကိုယ်တိုင် တည်ဆောက်ပါ) လုပ်ပါ။ Button ကို နှိပ်တဲ့အခါ text field ထဲမှာ ရိုက်ထည့်ထားတဲ့ နာမည်ကို ရှေ့နဲ့ နောက်မှာ space မပါဘဲ စာလုံးကြီးနဲ့ label မှာ ပြရပါမယ် (ဥပမာ “ mia “ က “MIA” ဖြစ်သွားပါတယ်)။ -
ရေတွက်တဲ့ App (4 marks): ဂဏန်း တစ်ခု (0 ကနေ စ) ကို ပြတဲ့
Labelတစ်ခုနဲ့ “+” နဲ့ “-“ ဆိုတဲ့ button နှစ်ခု ပါတဲ့ application တစ်ခုကို Construct လုပ်ပါ။ “+” ကို နှိပ်ရင် ဂဏန်းကို 1 တိုးပြီး “-“ ကို နှိပ်ရင် 1 လျှော့ပါ၊ ဒါကြောင့် 0 မှာ “-“ ကို တစ်ချက် နှိပ်ရင် -1 ကို ပြပါတယ်။ နှိပ်ပြီးတိုင်း label ကို update လုပ်ရပါမယ်။
Extension (တိုးချဲ့ အဆင့်)
-
စာဖတ်ချိန် ခန့်မှန်းတဲ့ App (6 marks): စာအုပ် တစ်အုပ်ရဲ့ စာမျက်နှာ အရေအတွက်အတွက်
TextFieldတစ်ခု၊ စာဖတ်နှုန်း ရွေးဖို့ComboBoxတစ်ခု (“Slow: 20 pages an hour”၊ “Medium: 30 pages an hour” ဒါမှမဟုတ် “Fast: 45 pages an hour”၊ ဆိုလိုတာက နှေး: တစ်နာရီ 20 မျက်နှာ၊ အလယ်အလတ်: တစ်နာရီ 30 မျက်နှာ၊ မြန်: တစ်နာရီ 45 မျက်နှာ)၊ “Estimate” button တစ်ခုနဲ့ စာဖတ်ချိန်ကို နာရီနဲ့ မိနစ်နဲ့ ပြတဲ့Labelတစ်ခု ပါတဲ့ app တစ်ခုကို Construct လုပ်ပါ (ဥပမာ မြန်တဲ့ နှုန်းနဲ့ဆိုရင် 250 မျက်နှာက 5 နာရီ 33 မိနစ်လောက် ကြာပါတယ်)။ မခန့်မှန်းခင် input က 1 ကနေ 5000 အထိ ကိန်းပြည့် ဟုတ်မဟုတ် စစ်ပြီး မဟုတ်ရင် label ထဲမှာ message တစ်ခု ပြပါ။ -
ခရီးစဉ် စာရင်းပေးသွင်းတဲ့ List (6 marks): နေရာ 20 ရှိတဲ့ အတန်း ခရီးစဉ် တစ်ခုအတွက် app တစ်ခုကို Construct လုပ်ပါ။ User က နာမည် တစ်ခု ရိုက်ထည့်ပြီး “Sign Up” ကို နှိပ်ရင် အဲဒီ နာမည်ကို
ArrayList<String>ထဲ ထည့်ပါတယ်။ အဲဒီ list ကိုTextAreaထဲမှာ နံပါတ်တပ်ထားတဲ့ စာရင်းအဖြစ် ပြပါ။ နာမည် အလွတ်၊ list ထဲမှာ ရှိပြီးသား နာမည် (စာလုံး အကြီး အသေး မတူရင်တောင်) နဲ့ နေရာ 20 လုံး ပြည့်သွားပြီးနောက် စာရင်းပေးသွင်းတာ မှန်သမျှကို လက်မခံပါနဲ့။ တစ်ခါစီမှာ status label ထဲ message တစ်ခု ပြပါ။ နောက်ဆုံး ထည့်ခဲ့တဲ့ နာမည်ကို မဖယ်ခင် အတည်ပြုချက် တောင်းတဲ့ “Remove Last” button တစ်ခုလည်း ထည့်ပါ။
Challenge (စိန်ခေါ်မှု အဆင့်)
-
ကျောင်းသား စာရင်းသွင်းခြင်း (8 marks): နာမည်၊ အတန်း (11 ဒါမှမဟုတ် 12 ပါတဲ့ ComboBox) နဲ့ HL/SL (CheckBox) အတွက် field တွေ ပါတဲ့ form တစ်ခုကို Construct လုပ်ပါ (HL (Higher Level) နဲ့ SL (Standard Level) ဆိုတာ IB သင်တန်းရဲ့ အဆင့်နှစ်ဆင့်ပါ)။ နာမည် ရိုက်ထည့်ထားပြီး အတန်း ရွေးထားပြီလား စစ်ပြီး ကျောင်းသားရဲ့ အချက်အလက်ကို အရင် စာရင်းသွင်းထားတဲ့ ကျောင်းသားတွေရဲ့ အောက်မှာ ဖတ်ရုံသာ ရတဲ့
TextAreaထဲက line အသစ် တစ်ကြောင်းအဖြစ် ထည့်ပေးတဲ့ “Register” button တစ်ခု ထည့်ပါ။ Field အားလုံးကို default (သတ်မှတ်မထားရင် သုံးတဲ့) တန်ဖိုးတွေဆီ ပြန်ထားပေးတဲ့ “Clear Form” button တစ်ခုလည်း ထည့်ပါ။ -
Event တွေ ဖြစ်တဲ့ အစဉ်ကို ဖော်ပြပါ (6 marks): အားလုံးကို ပေါင်းစပ်ခြင်း ထဲက Name List Manager မှာ user က app ကို စဖွင့်ပြီး “Mia” လို့ ရိုက်ထည့်ကာ Add ကို နှိပ်ပါတယ်။
launch(args)run တဲ့ အချိန်ကနေ display ထဲမှာ “1. Mia” ပေါ်လာတဲ့အထိ program က ဘာတွေ လုပ်လဲဆိုတာကို အစဉ်လိုက် Describe (ဖော်ပြရှင်းပြပါ) လုပ်ပါ။start()ဘယ်အချိန်မှာ run လဲ၊addBtn.setOnAction(...)ထဲက code ဘယ်အချိန်မှာ run လဲ၊ အဲဒီ code က display ကို ကိုယ်တိုင် update မလုပ်ဘဲ ဘာကြောင့်refreshDisplay()ကို ခေါ်သလဲ ဆိုတာတွေကို ထည့်ရေးပါ။ Code ရေးဖို့ မလိုပါဘူး။
ဆက်စပ် ခေါင်းစဉ်များ
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Classes and Objects (class နဲ့ object များ): JavaFX app တွေက
Applicationကို extend လုပ်တဲ့ class တွေပါ - အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Encapsulation (ဒေတာနဲ့ method ကို တစ်စုတည်း ထုပ်ပိုးခြင်း): control တွေက getter (private attribute ရဲ့ တန်ဖိုးကို ပြန်ပေးတဲ့ method) နဲ့ setter (private attribute ရဲ့ တန်ဖိုးကို ပြောင်းတဲ့ method) တွေကို သုံးပါတယ် (
getText(),setText()) - နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်: MVC Architecture: ဒေတာ၊ display နဲ့ logic ကို ခွဲခြားခြင်း
- နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်: FXML and Controllers: layout ကို Java code ထဲမှာ မဟုတ်ဘဲ FXML file ထဲမှာ သတ်မှတ်ခြင်း
- နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်: File I/O in Apps: ဒေတာကို သိမ်းခြင်းနဲ့ ပြန် load လုပ်ခြင်း
- ဆက်စပ် ခေါင်းစဉ်: JavaFX Cookbook (JavaFX code နမူနာ စုစည်းမှု): အသုံးများတဲ့ feature တွေ (table တွေ၊ file chooser တွေ၊ chart တွေ) အတွက် ပုံစံ တိုတိုလေးတွေ၊ FXML နဲ့ controller တွေနဲ့ ရေးထားပါတယ်