Time, progress, and animation (အချိန်၊ အလုပ် ပြီးမြောက်မှုနဲ့ animation)

IA အတွက် tool တွေပါ၊ စာမေးပွဲ ခေါင်းစဉ် မဟုတ်ပါဘူး။ ဒါတွေက ကိုယ့် IA (Internal Assessment: IB သင်တန်းမှာ ကျောင်းသားတစ်ယောက်ချင်း ကိုယ်တိုင် တည်ဆောက်ရပြီး ကျောင်းက ဆရာက အမှတ်ပေးတဲ့ အပိုင်း) နဲ့ ကိုက်အောင် ပြင်သုံးရမယ့် JavaFX (Java နဲ့ desktop app တည်ဆောက်တဲ့ library) code ပုံစံတွေပါ။ ဒီစာမျက်နှာက ဘယ်အရာကိုမှ စာမေးပွဲမှာ မမေးပါဘူး၊ ပြီးတော့ ကိုယ့် IA က ကိုယ်တိုင် လုပ်ထားတဲ့ အလုပ် ဖြစ်ရပါမယ်။

ဒီစာမျက်နှာက အချိန်နဲ့ ဆိုင်တဲ့ လိုအပ်ချက် နှစ်ခုကို ပြပါတယ်: အချိန်မှန်မှန် ထပ်ခါထပ်ခါ တစ်ခုခု လုပ်တာနဲ့ အလုပ် တစ်ခု ဘယ်လောက် ပြီးပြီလဲ ပြတာပါ။

ဒီ cookbook (recipe တွေကို စုထားတဲ့ လမ်းညွှန်) ကို ပထမဆုံး ဖတ်တာလား။ Start here: how every recipe fits together (ဒီမှာ စပါ: recipe တိုင်း ဘယ်လို ချိတ်ဆက်ထားလဲ) ကို အရင် ဖတ်ပါ။ အဲဒီ စာမျက်နှာက ကိုယ် ပြင်ရမယ့် နေရာ နှစ်ခုကို ရှင်းပြထားပြီး recipe (ချက်ချင်း ယူသုံးလို့ရတဲ့ code နမူနာ) တိုင်း အားကိုးရတဲ့ fx:id (screen ပေါ်က button၊ text box စတာတွေကို code ထဲက variable နဲ့ ချိတ်တဲ့ နာမည်) ချိတ်ဆက်မှုကိုလည်း ရှင်းပြထားပါတယ်။


အချိန်မှန်မှန် ထပ်ခါထပ်ခါ တစ်ခုခု လုပ်ခြင်း

ဒါက ဘာလုပ်ပေးလဲ: code အပိုင်း တစ်ခုကို ပုံသေ အချိန်ခြားပြီး run ပေးပါတယ်၊ ဥပမာ တစ်စက္ကန့်ကို တစ်ကြိမ်။ Countdown timer (အချိန်ကို ပြောင်းပြန် ရေတွက်တဲ့ နာရီ) ဒါမှမဟုတ် နာရီ တစ်ခုရဲ့ နောက်ကွယ်မှာ အလုပ်လုပ်ပေးတဲ့ အပိုင်းက ဒါပါပဲ။

IA မှာ ဘယ်အချိန် သုံးမလဲ: quiz ဒါမှမဟုတ် game အတွက် countdown၊ တစ်စက္ကန့်တိုင်း update ဖြစ်တဲ့ နာရီ ဒါမှမဟုတ် အချိန်မှန်မှန် အသစ် ပြန်ပြတဲ့ status line (အခြေအနေ ပြတဲ့ စာကြောင်း) တစ်ခုမှာ သုံးပါတယ်။

SceneBuilder မှာ (layout): SceneBuilder (FXML layout ကို ပုံနဲ့ မြင်ရင်း ပြင်တဲ့ editor) ထဲက layout (control တွေကို screen ပေါ်မှာ စီစဉ်ထားပုံ) မှာ ရေတွက်နေတဲ့ ဂဏန်းကို ပြဖို့ Label တစ်ခု (fx:id ကို lblCountdown) ထည့်ပါ။ စတင်ဖို့ button တစ်ခုလည်း ထည့်ပြီး သူ့ onAction (button နှိပ်ရင် run မယ့် method ကို သတ်မှတ်တဲ့ setting) ကို handleStart လို့ သတ်မှတ်ပါ။ Timeline (အချိန်ကိုက် code ကို ထပ်ခါထပ်ခါ run ပေးတဲ့ JavaFX object) ကိုယ်တိုင်ကိုတော့ code ထဲမှာ ဖန်တီးပါတယ်။

<Label fx:id="lblCountdown" text="60" />
<Button text="Start" onAction="#handleStart" />

Controller (user လုပ်တာတွေကို ကိုင်တွယ်ပြီး Model နဲ့ screen တွေကို ချိတ်ပေးတဲ့ class) မှာ (.java file):

Import (တခြားနေရာက code ကို ယူသုံးမယ်လို့ ကြေညာခြင်း) line များ:

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.util.Duration;
import javafx.fxml.FXML;
import javafx.scene.control.Label;

Controller ထဲက code:

@FXML private Label lblCountdown;

private int secondsLeft = 60;
private Timeline timeline;

@FXML
public void initialize() {
    // One KeyFrame that fires every second and calls tick().
    timeline = new Timeline(new KeyFrame(Duration.seconds(1), event -> tick()));
    timeline.setCycleCount(Animation.INDEFINITE);   // keep repeating
    lblCountdown.setText(String.valueOf(secondsLeft));
}

@FXML
private void handleStart() {
    timeline.play();
}

private void tick() {
    // your IA logic here: what should happen on each beat
    secondsLeft--;
    lblCountdown.setText(String.valueOf(secondsLeft));
    if (secondsLeft <= 0) {
        timeline.stop();
    }
}

ကိုယ်ပိုင် logic (ဘာလုပ်မလဲ ဆုံးဖြတ်တဲ့ code) ထည့်ရမယ့် နေရာ: tick() ထဲက // your IA logic here (ကိုယ့် IA ရဲ့ logic ကို ဒီမှာ ထည့်ပါ) လို့ မှတ်ထားတဲ့ နေရာမှာ ထည့်ပါ။ အဲဒီ body က အချိန်တစ်ချက် ရောက်တိုင်း ဖြစ်မယ့် အလုပ်ပါ။ Timeline ကို တည်ဆောက်တာနဲ့ စတင်တာကတော့ ပြန်သုံးလို့ရတဲ့ wiring (screen နဲ့ code ကို ချိတ်ပေးတဲ့၊ ဘယ် project မှာမဆို တူတဲ့ code) ပါ။

ကိုယ့် project နဲ့ ကိုက်အောင် ပြင်ပါ:

  • အချိန်ခြားကို သတ်မှတ်ဖို့ Duration.seconds(1) ကို ပြောင်းပါ။ Duration.millis(500) က တစ်စက္ကန့်ကို နှစ်ကြိမ် run ပါတယ်။
  • အချိန်တစ်ချက် ရောက်တိုင်း ဖြစ်ရမယ့် အရာ မှန်သမျှကို tick() ထဲမှာ ထည့်ပါ။
  • ပြီးသွားရင် timeline.stop() ကို ခေါ်ပါ၊ စတင်ဖို့ ဒါမှမဟုတ် ရပ်ထားရာကနေ ဆက်ဖို့ timeline.play() ကို ခေါ်ပါ။

သတိထားရမယ့် အချက်များ:

  • fx:id lblCountdown က @FXML field (object ထဲက အချက်အလက် အကွက်) ရဲ့ နာမည်နဲ့ ကိုက်ရပါမယ်၊ handleStart ကလည်း controller ထဲမှာ ရှိရပါမယ်။ မဟုတ်ရင် screen က load မဖြစ်ပါဘူး။
  • ထပ်ခါထပ်ခါ run အောင် လုပ်ပေးတာက setCycleCount(Animation.INDEFINITE) ပါ။ အဲဒါ မပါရင် တစ်ကြိမ်ပဲ run ပြီး ရပ်သွားပါတယ်။
  • event -> tick() အပိုင်းက lambda (နာမည် မပါတဲ့ method အတိုလေး) တစ်ခုပါ။ Lambda တွေက စာမေးပွဲမှာ စစ်တဲ့ Java အပိုင်းထဲမှာ မပါပေမယ့် KeyFrame ကို သူလုပ်ရမယ့် အလုပ် ပေးတဲ့ စံ နည်းလမ်းပါ။
  • Screen ကို ပိတ်တဲ့အခါ ဒါမှမဟုတ် ရေတွက်တာ သုည ရောက်တဲ့အခါ timeline ကို ရပ်ဖို့ မမေ့ပါနဲ့၊ မဟုတ်ရင် နောက်ကွယ်မှာ ဆက် run နေပါလိမ့်မယ်။

တွဲသုံးလို့ရတဲ့ recipe များ: ပန်းတိုင်ဆီ ဘယ်လောက် ရောက်ပြီလဲ ပြခြင်း၊ User ကို တစ်ခုခု အသိပေးခြင်း။


ပန်းတိုင်ဆီ ဘယ်လောက် ရောက်ပြီလဲ ပြခြင်း

ဒါက ဘာလုပ်ပေးလဲ: အလုပ် တစ်ခု ဘယ်လောက် ပြီးပြီလဲ ပြဖို့ ဘား တစ်ခုကို အလွတ်ကနေ အပြည့်အထိ ဖြည့်ပေးပါတယ်။

IA မှာ ဘယ်အချိန် သုံးမလဲ: အဆင့် အများ ပါတဲ့ form (ဒေတာ ဖြည့်ရတဲ့ အကွက်တွေ ပါတဲ့ အပိုင်း) မှာ ဘယ်အဆင့် ရောက်ပြီလဲ၊ quiz တစ်ခုရဲ့ မေးခွန်း ဘယ်နှစ်ခု ပြီးပြီလဲ ဒါမှမဟုတ် booking တစ်ခုက သူ့ capacity (ဆံ့နိုင်တဲ့ ပမာဏ) နဲ့ ယှဉ်ရင် ဘယ်လောက် ပြည့်နေပြီလဲ ပြဖို့ သုံးပါတယ်။ ပုံနဲ့ မြင်သာအောင် ပြချင်တဲ့ “y ထဲက x” မှန်သမျှအတွက် သုံးနိုင်ပါတယ်။

SceneBuilder မှာ (layout): ProgressBar (အလုပ် ဘယ်လောက် ပြီးပြီလဲ ပြတဲ့ ဘား) တစ်ခု ထည့်ပြီး သူ့ကို pbProgress ဆိုတဲ့ fx:id ပေးပါ။ ဒီမှာ တခြား ထည့်စရာ မရှိပါဘူး။

<ProgressBar fx:id="pbProgress" progress="0" />

Controller မှာ (.java file):

Import line များ:

import javafx.fxml.FXML;
import javafx.scene.control.ProgressBar;

Controller ထဲက code:

@FXML private ProgressBar pbProgress;

private void showProgress(int done, int total) {
    // setProgress takes a value from 0.0 (empty) to 1.0 (full).
    pbProgress.setProgress((double) done / total);
}

ကိုယ်ပိုင် logic ထည့်ရမယ့် နေရာ: ကိုယ်ပိုင် code ထဲကနေ လက်ရှိ ရေတွက်ထားတဲ့ အရေအတွက် (running count) နဲ့ ပန်းတိုင် အရေအတွက်ကို ပေးပြီး showProgress(done, total) ကို ခေါ်ပါ:

// your IA logic here: work out done and total from your data
showProgress(answered, questionCount);

ကိုယ့် project နဲ့ ကိုက်အောင် ပြင်ပါ:

  • ကိုယ့် လက်ရှိ အရေအတွက်နဲ့ ပန်းတိုင် အရေအတွက်ကို ပေးပြီး showProgress(done, total) ကို ခေါ်ပါ။
  • ဘားကို ကိုယ့် ဒေတာက ထိန်းထားတာမို့ done ပြောင်းတိုင်း ဘားကို update လုပ်ပါ။

သတိထားရမယ့် အချက်များ:

  • fx:id pbProgress က @FXML field ရဲ့ နာမည်နဲ့ အတိအကျ ကိုက်ရပါမယ်။ မကိုက်ရင် screen က load ဖြစ်ပေမဲ့ field က null (ဘာ object ကိုမှ မညွှန်းတဲ့ တန်ဖိုး) ဖြစ်နေပြီး showProgress ကို ခေါ်တဲ့အခါ error ဖြစ်ပါလိမ့်မယ်။
  • တန်ဖိုးက 0 ကနေ 100 မဟုတ်ဘဲ 0.0 ကနေ 1.0 အထိပါ။ တန်ဖိုး 50 က ဘား တစ်ဝက် မဟုတ်ဘဲ ဘား အပြည့် အဖြစ် ပေါ်ပါတယ်။
  • စားတာကို ဒသမ ကိန်းနဲ့ တွက်အောင် (double) done / total ကို သုံးပါ။ Cast (type ပြောင်း) မပါရင် done / total က integer division (ကိန်းပြည့် အချင်းချင်း စားရင် ဒသမ ပျောက်သွားတာ) ဖြစ်ပြီး done က total ကို မရောက်မချင်း 0 ကို ပေးပါတယ်။
  • တန်ဖိုးကို -1 လို့ သတ်မှတ်ရင် ဘားက “unknown” (မသိ) ဆိုတဲ့ animation (ရွေ့လျားနေတဲ့ ပုံ) အခြေအနေကို ရောက်သွားပါတယ်၊ ဘယ်လောက် ကျန်သေးလဲ မတိုင်းနိုင်တဲ့အခါ အသုံးဝင်ပါတယ်။

တွဲသုံးလို့ရတဲ့ recipe များ: အချိန်မှန်မှန် ထပ်ခါထပ်ခါ တစ်ခုခု လုပ်ခြင်း၊ ကြာတဲ့ အလုပ် လုပ်နေစဉ် UI ကို တုံ့ပြန်နေအောင် ထားခြင်း (UI ဆိုတာ user interface၊ user နဲ့ program ကြားက မြင်ကွင်း)၊ ဒေတာ ပြောင်းတဲ့အခါ chart ကို update လုပ်ခြင်း။