Images and media (ပုံများနဲ့ media)

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

ဒီစာမျက်နှာမှာ ပုံ တစ်ပုံ ပြတာ၊ user ကို ပုံ ရွေးခိုင်းတာ၊ ပုံကို button ရဲ့ icon (သင်္ကေတ ပုံလေး) အဖြစ် သုံးတာနဲ့ အသံ ဖွင့်တာတို့ကို လေ့လာပါမယ်။ ဒါတွေ အားလုံးအတွက် runtime (program run နေစဉ်) မှာ ရှာတွေ့အောင် media file က ကိုယ့် project နဲ့ အတူ ပါသွားရပါမယ်။

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


ပုံ တစ်ပုံ ပြခြင်း

ဒါက ဘာလုပ်ပေးလဲ: ကိုယ့် project နဲ့ အတူ ပါတဲ့ file တစ်ခုကနေ load လုပ်ပြီး ImageView ထဲမှာ ပုံ တစ်ပုံကို ပြပါတယ်။

ကိုယ့် IA မှာ ဘယ်အခါ သုံးမလဲ: logo၊ icon၊ ကုန်ပစ္စည်း ဓာတ်ပုံ ဒါမှမဟုတ် app က ပြတဲ့ မပြောင်းလဲတဲ့ ပုံ ဘယ်ဟာမဆို။

SceneBuilder ထဲမှာ (layout): SceneBuilder (FXML layout ကို ပုံနဲ့ မြင်ရင်း ပြင်တဲ့ editor) ထဲက layout (control တွေကို screen ပေါ်မှာ စီစဉ်ထားပုံ) မှာ ImageView တစ်ခု ထည့်ပြီး imgLogo ဆိုတဲ့ fx:id ပေးပါ။ ပုံ ဆွဲမဆန့်သွားအောင် fitWidth ကို သတ်မှတ်ပြီး preserveRatio ကို ဖွင့်ပါ။

<ImageView fx:id="imgLogo" fitWidth="200" preserveRatio="true" />

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

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

import javafx.fxml.FXML;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

Controller ထဲမှာ:

@FXML private ImageView imgLogo;

@FXML
public void initialize() {
    // your IA logic here: the image file your app should show
    // logo.png sits next to this class in the project.
    Image image = new Image(getClass().getResourceAsStream("logo.png"));
    imgLogo.setImage(image);
}

ကိုယ်ပိုင် logic (ဘာလုပ်မလဲ ဆုံးဖြတ်တဲ့ code) ကို ဘယ်မှာ ထည့်ရမလဲ: // your IA logic here (ကိုယ့် IA ရဲ့ logic ကို ဒီမှာ ထည့်ပါ) လို့ မှတ်ထားတဲ့ load လုပ်မယ့် ပုံ file ပါ။ Image ကို ဖန်တီးပြီး ImageView ထဲ ထည့်တာက ပြန်သုံးလို့ရတဲ့ wiring (control တွေနဲ့ code ကို ချိတ်ဆက်ပေးတဲ့ အသင့် code) ပါ။

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

  • "logo.png" ကို ကိုယ့် file အဖြစ် ပြောင်းပါ၊ ပြီးရင် getResourceAsStream ရှာတွေ့အောင် အဲဒီ file ကို ကိုယ့် class (object တွေ ဖန်တီးဖို့ ပုံစံခွက်) တွေ ရှိတဲ့ နေရာမှာပဲ ထားပါ။
  • fitWidth က ပြမယ့် အကျယ်ကို သတ်မှတ်ပါတယ်၊ preserveRatio="true" က ပုံ ဆွဲမဆန့်သွားအောင် တားပေးပါတယ်။

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

  • fx:id imgLogo က @FXML field (FXML ထဲက control နဲ့ ချိတ်ထားတဲ့ controller ထဲက variable) နာမည်နဲ့ အတိအကျ ကိုက်ရပါမယ်။ မကိုက်ရင် screen က load မဖြစ်ပါဘူး။
  • Code ရှာတဲ့ နေရာမှာ file ကို ရှာမတွေ့ရင် getResourceAsStream("logo.png") က null (ဘာ object ကိုမှ မညွှန်းတဲ့ တန်ဖိုး) ကို return (ရလဒ်အဖြစ် ပြန်ပေး) လုပ်ပါတယ်။ အဲဒီအခါ initialize() ထဲက new Image(...) က NullPointerException (null ပေါ်မှာ အလုပ်လုပ်ခိုင်းလို့ ဖြစ်တဲ့ exception၊ program run နေစဉ် ဖြစ်တဲ့ အမှား) ကို throw (exception ဖြစ်ကြောင်း အချက်ပြ) လုပ်လို့ screen က load မဖြစ်ပါဘူး။ File နာမည်နဲ့ project ထဲက သူ့ နေရာကို စစ်ပါ။
  • preserveRatio မပါဘဲ fitWidth ရော fitHeight ကိုပါ သတ်မှတ်ရင် ပုံ ပြားသွားပါတယ်။ အချိုး ထိန်းတဲ့ setting ကို ဖွင့်ပါ၊ ဒါမှမဟုတ် အတိုင်းအတာ တစ်ခုကိုပဲ သတ်မှတ်ပါ။

တွဲသုံးလို့ရတဲ့ recipe များ: User ကို ပုံ ရွေးခိုင်းပြီး ပြခြင်း၊ Button ပေါ်မှာ ပုံ ထည့်ခြင်း။


User ကို ပုံ ရွေးခိုင်းပြီး ပြခြင်း

ဒါက ဘာလုပ်ပေးလဲ: user ကို disk ပေါ်က ပုံ file တစ်ခု ရွေးခွင့်ပေးပြီး ImageView ထဲမှာ ပြပါတယ်။

ကိုယ့် IA မှာ ဘယ်အခါ သုံးမလဲ: user က upload လုပ်တဲ့ profile ပုံ၊ ဒါမှမဟုတ် ကိုယ် project နဲ့ ထည့်ပေးထားတဲ့ ပုံ မဟုတ်ဘဲ user ကိုယ်ပိုင် ပုံကို သုံးတဲ့ ဘယ် app မှာမဆို။

SceneBuilder ထဲမှာ (layout): ImageView (fx:id imgPhoto) တစ်ခုနဲ့ file ရွေးဖို့ button တစ်ခုကို ထည့်ပါ။ အဲဒီ button ရဲ့ onAction (button နှိပ်ရင် run မယ့် method ကို သတ်မှတ်တဲ့ setting) က handleChoosePhoto ပါ။

<ImageView fx:id="imgPhoto" fitWidth="200" preserveRatio="true" />
<Button text="Choose photo..." onAction="#handleChoosePhoto" />

Controller ထဲမှာ (.java file): ဒါက file ရွေးခိုင်းတဲ့ recipe ကို ImageView နဲ့ ပေါင်းထားတာပါ။

Import line များ:

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import java.io.File;

Controller ထဲမှာ:

@FXML private ImageView imgPhoto;

@FXML
private void handleChoosePhoto(ActionEvent event) {
    FileChooser chooser = new FileChooser();
    chooser.getExtensionFilters().add(
        new FileChooser.ExtensionFilter("Images", "*.png", "*.jpg", "*.gif"));

    Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
    File file = chooser.showOpenDialog(stage);
    if (file == null) {
        return;                                  // the user cancelled
    }
    // your IA logic here: what to do with the chosen image (here, show it)
    imgPhoto.setImage(new Image(file.toURI().toString()));
}

ကိုယ်ပိုင် logic ကို ဘယ်မှာ ထည့်ရမလဲ: // your IA logic here လို့ မှတ်ထားတဲ့ line ပါ၊ အဲဒီမှာ ရွေးထားတဲ့ file ကို သုံးပါ (ပြတာ ဒါမှမဟုတ် copy ကူးပြီး သူ့ path (file ရှိရာ လမ်းကြောင်း) ကို မှတ်ထားတာ)။ Dialog (file ရွေးဖို့ ပေါ်လာတဲ့ window) နဲ့ Cancel ကို ကိုင်တွယ်တာက ပြန်သုံးလို့ရတဲ့ wiring ပါ။

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

  • ကိုယ် လက်ခံမယ့် ပုံ အမျိုးအစားတွေနဲ့ ကိုက်အောင် extension filter (file နာမည် အဆုံးက .png လို အပိုင်းနဲ့ file တွေကို စစ်ထုတ်တဲ့ filter) ကို ပြင်ပါ။
  • file.toURI().toString() က ရွေးထားတဲ့ File ကို Image က load လုပ်နိုင်တဲ့ လိပ်စာ တစ်ခုအဖြစ် ပြောင်းပေးပါတယ်။ User ရွေးတဲ့ file တွေအတွက် getResourceAsStream အစား ဒီပုံစံကို သုံးပါ၊ getResourceAsStream က ကိုယ့် project ထဲမှာ ပါတဲ့ file တွေအတွက်ပါ။

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

  • fx:id imgPhoto က @FXML field နာမည်နဲ့ ကိုက်ရပါမယ်။ မကိုက်ရင် screen က load ဖြစ်ပေမဲ့ field က null ဖြစ်နေပြီး ရွေးလိုက်တဲ့ ပုံကို ပြတဲ့အခါ error ဖြစ်ပါလိမ့်မယ်။ handleChoosePhoto ကတော့ controller ထဲမှာ ရှိရပါမယ်၊ မရှိရင် screen က load မဖြစ်ပါဘူး။
  • File ရွေးခိုင်းတဲ့ recipe မှာလိုပဲ Cancel လုပ်လိုက်တဲ့ dialog ကနေ ပြန်လာတဲ့ null ကို ကိုင်တွယ်ပါ။
  • Program ကို ပိတ်ပြီး ပြန်ဖွင့်တဲ့အခါမှာလည်း ပုံ ဆက်ရှိနေစေချင်ရင် file path ကို save လုပ်ဖို့ (ဒါမှမဟုတ် file ကို ကိုယ့် project folder ထဲ copy ကူးဖို့) မမေ့ပါနဲ့၊ ဘာလို့လဲဆိုတော့ user ရဲ့ မူရင်း file က တခြားနေရာကို ရွှေ့သွားနိုင်လို့ပါ။

တွဲသုံးလို့ရတဲ့ recipe များ: Let the user choose a file (user ကို file ရွေးခွင့်ပေးခြင်း)၊ ပုံ တစ်ပုံ ပြခြင်း။


Button ပေါ်မှာ ပုံ ထည့်ခြင်း

ဒါက ဘာလုပ်ပေးလဲ: ပုံ အသေးလေး တစ်ခုကို button ရဲ့ icon အဖြစ် သတ်မှတ်ပေးပါတယ်၊ ဘေးမှာ စာသား ပါချင်လည်း ပါ၊ မပါချင်လည်း ရပါတယ်။

ကိုယ့် IA မှာ ဘယ်အခါ သုံးမလဲ: icon button တွေ (save၊ delete၊ edit) တန်းစီထားတဲ့ toolbar (button တွေကို တန်းစီထားတဲ့ ဘား) တစ်ခု၊ ဒါမှမဟုတ် ပုံနဲ့ ထင်ရှားစေချင်တဲ့ button တစ်ခုတည်း။

SceneBuilder ထဲမှာ (layout): Button တစ်ခု ထည့်ပြီး btnSave ဆိုတဲ့ fx:id ပေးပါ။ Icon ကို code ထဲမှာ သတ်မှတ်ပါတယ်။

<Button fx:id="btnSave" text="Save" onAction="#handleSave" />

Controller ထဲမှာ (.java file):

Import line များ:

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

Controller ထဲမှာ:

@FXML private Button btnSave;

@FXML
public void initialize() {
    // your IA logic here: the icon file for this button
    Image icon = new Image(getClass().getResourceAsStream("save.png"));
    ImageView iconView = new ImageView(icon);
    iconView.setFitWidth(16);
    iconView.setFitHeight(16);
    btnSave.setGraphic(iconView);            // the image becomes the button's icon
}

ကိုယ်ပိုင် logic ကို ဘယ်မှာ ထည့်ရမလဲ: // your IA logic here လို့ မှတ်ထားတဲ့ icon file ပါ။ ImageView ရဲ့ အရွယ်အစား သတ်မှတ်တာနဲ့ အဲဒါကို button ရဲ့ graphic (button ပေါ်မှာ ပြတဲ့ ပုံ) အဖြစ် သတ်မှတ်တာက ပြန်သုံးလို့ရတဲ့ wiring ပါ။

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

  • ကိုယ့် icon နဲ့ ကိုက်အောင် ပုံ file နဲ့ setFitWidth / setFitHeight တန်ဖိုးတွေကို ပြောင်းပါ။
  • Button မှာ စာသားလည်း ဆက်ထားလို့ ရပါတယ်: graphic ရော စာသားပါ သတ်မှတ်ထားရင် icon က button ရဲ့ စာသား ဘေးမှာ ပေါ်ပါတယ်။

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

  • fx:id btnSave က @FXML field နာမည်နဲ့ အတိအကျ ကိုက်ရပါမယ်။ မကိုက်ရင် screen က load မဖြစ်ပါဘူး။
  • (အပေါ်မှာလို) ImageView ရဲ့ အရွယ်အစားကို သတ်မှတ်ပါ၊ မဟုတ်ရင် ပုံကြီး တစ်ပုံက button ကို ပုံပျက်အောင် ဖောင်းကားသွားစေပါလိမ့်မယ်။
  • Button တွေ တန်းညီနေအောင် toolbar တစ်ခုလုံးမှာ icon တွေကို သေးသေးလေးနဲ့ အရွယ်အစား တူတူ ထားပါ။

တွဲသုံးလို့ရတဲ့ recipe များ: Make your app look finished (app ကို ပြီးပြည့်စုံတဲ့ ပုံစံ ဖြစ်အောင် လုပ်ခြင်း)၊ ပုံ တစ်ပုံ ပြခြင်း။


အသံ ဖွင့်ခြင်း

ဒါက ဘာလုပ်ပေးလဲ: ကိုယ့် project နဲ့ အတူ ပါတဲ့ file ကနေ အသံကို ဖွင့်ပေးပါတယ်။ AudioClip က အသံ effect တိုတိုလေးတွေအတွက် အကောင်းဆုံးပါ၊ MediaPlayer က ပိုရှည်တဲ့ တေးဂီတအတွက်ပါ။

ကိုယ့် IA မှာ ဘယ်အခါ သုံးမလဲ: အတည်ပြုချက် ဒါမှမဟုတ် error ကို ပြတဲ့ အသံတိုလေး၊ ဒါမှမဟုတ် game ပုံစံ app ထဲက နောက်ခံ တေးဂီတ။ အသံက မဖြစ်မနေ မလိုလို့ project အတွက် တကယ် အသုံးဝင်မှသာ ထည့်ပါ။

SceneBuilder ထဲမှာ (layout): အသံကို စတင်ပေးမယ့် control တစ်ခု (ဥပမာ button တစ်ခု) ကလွဲပြီး ဘာမှ ထည့်စရာ မလိုပါဘူး။ အသံကို code ထဲမှာ load လုပ်ပါတယ်။

Controller ထဲမှာ (.java file):

AudioClip နဲ့ အသံ effect တိုတို:

import javafx.scene.media.AudioClip;

// your IA logic here: which sound to play and when
AudioClip click = new AudioClip(getClass().getResource("click.wav").toExternalForm());
click.play();

MediaPlayer နဲ့ ပိုရှည်တဲ့ တေးဂီတ:

import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;

private MediaPlayer player;                      // a field, not a local variable (see below)

// in the method that starts the music:
Media media = new Media(getClass().getResource("theme.mp3").toExternalForm());
player = new MediaPlayer(media);
player.play();

ကိုယ်ပိုင် logic ကို ဘယ်မှာ ထည့်ရမလဲ: // your IA logic here လို့ မှတ်ထားတဲ့ ဘယ်အသံကို ဘယ်အချိန် ဖွင့်မလဲ ဆိုတာပါ။ Load လုပ်တာနဲ့ ဖွင့်တာက ပြန်သုံးလို့ရတဲ့ wiring ပါ။

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

  • File နာမည်တွေကို ကိုယ့် အသံ file တွေအဖြစ် ပြောင်းပါ၊ ပြီးရင် project နဲ့ အတူ ပါသွားအောင် အဲဒီ file တွေကို project ထဲမှာ ထားပါ။
  • မကြာခဏ ဖွင့်ရတဲ့ အသံတိုတွေအတွက် AudioClip ကို သုံးပါ၊ ပိုရှည်တဲ့ သီချင်း ဒါမှမဟုတ် အသံ file မှာ ဖွင့်၊ ခဏရပ်၊ ရပ် လုပ်ဖို့ လိုရင် MediaPlayer ကို သုံးပါ။

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

  • အသံ file က project နဲ့ အတူ ပါရပါမယ်။ getResource(...) က null ကို return လုပ်ရင် file မရှိတာ ဒါမှမဟုတ် နေရာ မှားနေတာပါ။
  • MediaPlayer ကို local variable (method ထဲမှာပဲ ရှိတဲ့ variable) မှာ မသိမ်းဘဲ field (object ထဲက အချက်အလက် အကွက်) မှာ သိမ်းပါ။ Local variable အဖြစ်ပဲ ရှိရင် garbage collector (မသုံးတော့တဲ့ memory ကို Java က အလိုအလျောက် ပြန်ရှင်းပေးတဲ့ အစိတ်အပိုင်း) က အဲဒါကို ရှင်းပစ်နိုင်ပြီး အသံက မမျှော်လင့်ဘဲ ရပ်သွားပါတယ်။
  • Media ကို ဖွင့်နိုင်မနိုင်က file ပုံစံ (format) နဲ့ system ပေါ် မူတည်ပါတယ်။ အသံ effect တွေအတွက် .wav၊ တေးဂီတအတွက် .mp3 လို အသုံးများတဲ့ ပုံစံတွေကိုပဲ သုံးပါ။

တွဲသုံးလို့ရတဲ့ recipe များ: Do something on a repeating beat (သတ်မှတ်ချိန် ခြားပြီး ထပ်ခါထပ်ခါ လုပ်ခြင်း)၊ Run a smooth animation or game loop (ချောမွေ့တဲ့ animation ဒါမှမဟုတ် game loop ကို run ခြင်း)။