Showing data in a table (ဒေတာကို ဇယားနဲ့ ပြခြင်း)

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

TableView က object (class တစ်ခုကနေ ဖန်တီးထားတဲ့ instance) list တစ်ခုကို row (အလျားလိုက် အတန်း) တွေနဲ့ column (ဒေါင်လိုက် ကော်လံ) တွေအဖြစ် ပြပါတယ်။ ကိုယ် သိပြီးသား OOP (object တွေကို အခြေခံပြီး program ရေးနည်း) နဲ့ တိုက်ရိုက် ဆက်စပ်ပါတယ်: row တစ်ခုက model class (ဒေတာ သိမ်းတဲ့ class) အသေးလေး တစ်ခုရဲ့ object တစ်ခုပါ၊ column တစ်ခုက အဲဒီ class ရဲ့ getter (private attribute ရဲ့ တန်ဖိုးကို ပြန်ပေးတဲ့ method) တစ်ခုကို ဖတ်ပါတယ်။ ဒီစာမျက်နှာမှာ table (ဇယား) ကို တည်ဆောက်တာ၊ ဒေတာ ဖြည့်တာ၊ ရွေးထားတဲ့ row ကို ဖတ်တာ၊ table ကို ဒေတာနဲ့ ကိုက်ညီနေအောင် ထားတာနဲ့ user ရိုက်နေစဉ်မှာပဲ filter (condition နဲ့ ကိုက်တာတွေကိုပဲ ရွေးထုတ်ခြင်း) လုပ်တာတို့ကို လုပ်ပါမယ်။

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


Scroll လုပ်လို့ရတဲ့ table ထဲမှာ row တွေကို ပြခြင်း

ဒါက ဘာလုပ်ပေးလဲ: ကိုယ့် object တွေကို နာမည်ပေးထားတဲ့ column တွေ ပါတဲ့ table အဖြစ် ပြပါတယ်။ Table ထဲမှာ ဆံ့တာထက် row တွေ ပိုများလာရင် table က သူ့ဘာသာ scroll (အပေါ်အောက် ရွှေ့ကြည့်) လုပ်လို့ ရလာပါတယ်။

ကိုယ့် IA မှာ ဘယ်အခါ သုံးမလဲ: client (product ကို သုံးမယ့်သူ) က တစ်ချက်ကြည့်ရုံနဲ့ မြင်ဖို့ လိုတဲ့ ဘယ် list မှာမဆို သုံးပါ: ကုန်ပစ္စည်းတွေ၊ ကြိုတင် စာရင်းသွင်းမှုတွေ၊ ကျောင်းသားတွေ၊ အရောင်းအဝယ် မှတ်တမ်းတွေ။ ဒေတာကို အဓိက ကိုင်တွယ်တဲ့ app မှာ table က များသောအားဖြင့် ပင်မ screen ဖြစ်ပါတယ်။

SceneBuilder ထဲမှာ (layout): SceneBuilder (FXML layout ကို ပုံနဲ့ မြင်ရင်း ပြင်တဲ့ editor) ထဲက layout (control တွေကို screen ပေါ်မှာ စီစဉ်ထားပုံ) မှာ TableView တစ်ခု ထည့်ပြီး tblItems ဆိုတဲ့ fx:id ပေးပါ။ ပြချင်တဲ့ field (object ထဲက အချက်အလက် အကွက်) တစ်ခုစီအတွက် TableColumn တစ်ခုစီ ထည့်ပါ၊ တစ်ခုစီကို fx:id (colName၊ colQuantity) ပေးပါ၊ ပြီးရင် column တစ်ခုစီရဲ့ text ကို user မြင်ရမယ့် ခေါင်းစဉ်အဖြစ် သတ်မှတ်ပါ။

<TableView fx:id="tblItems">
    <columns>
        <TableColumn fx:id="colName" text="Name" />
        <TableColumn fx:id="colQuantity" text="Quantity" />
    </columns>
</TableView>

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

ပထမဆုံး model class အသေးလေး တစ်ခု လိုပါတယ်။ ဒါက ပုံမှန် OOP ပါ၊ ဒီဇိုင်းကို ကိုယ်တိုင် ဆွဲရပါမယ်: getter တွေ ပါတဲ့ private (class အပြင်ကနေ တိုက်ရိုက် သုံးလို့ မရတဲ့) field တွေ၊ column တစ်ခုကို getter တစ်ခုစီ။

public class Item {
    private String name;
    private int quantity;

    public Item(String name, int quantity) {
        this.name = name;
        this.quantity = quantity;
    }

    public String getName() {
        return name;
    }

    public int getQuantity() {
        return quantity;
    }
}

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

import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;

Controller ကို စတင် ပြင်ဆင်ခြင်း:

@FXML private TableView<Item> tblItems;
@FXML private TableColumn<Item, String> colName;
@FXML private TableColumn<Item, Integer> colQuantity;

@FXML
public void initialize() {
    // The string must match the getter: getName() -> "name", getQuantity() -> "quantity".
    colName.setCellValueFactory(new PropertyValueFactory<>("name"));
    colQuantity.setCellValueFactory(new PropertyValueFactory<>("quantity"));
}

ကိုယ်ပိုင် logic (ဘာလုပ်မလဲ ဆုံးဖြတ်တဲ့ code) ကို ဘယ်မှာ ထည့်ရမလဲ: Item model class က ကိုယ့်ဟာပါ။ Row တစ်ခုက ဘာကို ကိုယ်စားပြုမလဲ ဆုံးဖြတ်ပြီး column တစ်ခုကို getter တစ်ခုစီ ပေးပါ။ initialize() ထဲက column တွေကို ချိတ်တဲ့ wiring (control တွေနဲ့ code ကို ချိတ်ဆက်ပေးတဲ့ အသင့် code) ကို ပြန်သုံးလို့ ရပါတယ်။

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

  • Item ကို ကိုယ့်ရဲ့ model class နဲ့ အစားထိုးပြီး ပြချင်တဲ့ column တစ်ခုကို getter တစ်ခုစီ ပေးပါ။
  • Column တစ်ခုစီအတွက် PropertyValueFactory string (စာသား) က getter နာမည်ထဲမှာ ပါတဲ့ field နာမည်ပါ: getPrice() ဆိုရင် "price" ဖြစ်ပါတယ်။
  • TableView<Item> ထဲက <Item> က “ဒီ table က Item object တွေကို သိမ်းတယ်” လို့ ပြောတဲ့ type parameter (class က ဘယ် type ကို သိမ်းမလဲ ပြတဲ့ < > ထဲက type) ပါ။ ArrayList<Item> (ArrayList: ကြီးလာ၊ သေးသွားနိုင်တဲ့ list) မှာလိုပဲ အလုပ်လုပ်ပါတယ်။

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

  • fx:id တန်ဖိုးတွေ (tblItems၊ colName၊ colQuantity) က @FXML field (FXML ထဲက control နဲ့ ချိတ်ထားတဲ့ controller ထဲက variable) နာမည်တွေနဲ့ အတိအကျ ကိုက်ရပါမယ်။ မကိုက်ရင် screen က load မဖြစ်ပါဘူး။
  • Column တစ်ခု ဗလာ ပေါ်နေရင် အဖြစ်အများဆုံး အကြောင်းရင်းက getter နာမည်နဲ့ မကိုက်တဲ့ PropertyValueFactory string ပါ။ စာလုံးပေါင်းနဲ့ စာလုံး အကြီး၊ အသေးကို စစ်ပါ။
  • Table က အလိုအလျောက် scroll လုပ်ပေးလို့ scroll bar (ဘေးမှာ ဆွဲရွှေ့ရတဲ့ ဘား) ကို ကိုယ်တိုင် ထည့်စရာ မလိုပါဘူး။

တွဲသုံးလို့ရတဲ့ recipe များ: ကိုယ့်ဒေတာနဲ့ table ကို ဖြည့်ခြင်း၊ User နှိပ်လိုက်တဲ့ row ကို သိအောင် လုပ်ခြင်း။


ကိုယ့်ဒေတာနဲ့ table ကို ဖြည့်ခြင်း

ဒါက ဘာလုပ်ပေးလဲ: ကိုယ့် object တွေကို ObservableList တစ်ခုထဲ ထုပ်ပြီး table ထဲ ထည့်ပေးပါတယ်။ ObservableList ဆိုတာ TableView က စောင့်ကြည့်နေတဲ့ အထူး list ပါ။

ကိုယ့် IA မှာ ဘယ်အခါ သုံးမလဲ: app စဖွင့်ချိန်မှာ သိမ်းထားတဲ့ record (အချက်အလက် အများကြီး စုထားတဲ့ ဒေတာ တစ်ခု) တွေကို load လုပ်တဲ့အခါ ဒါမှမဟုတ် program ရဲ့ တခြားနေရာမှာ တည်ဆောက်ပြီးသား ArrayList ထဲက ဒေတာတွေကို ပြတဲ့အခါ သုံးပါ။

SceneBuilder ထဲမှာ (layout): အသစ် ဘာမှ မလိုပါဘူး၊ ဒီ recipe က အရင် recipe က tblItems TableView ကို သုံးပါတယ်။

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

Import line များ:

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

Controller ထဲမှာ:

private final ObservableList<Item> items = FXCollections.observableArrayList();

@FXML
public void initialize() {
    // ... column setup from the previous recipe ...

    // your IA logic here: build Item objects from your own data
    items.add(new Item("Apples", 12));
    items.add(new Item("Bread", 3));

    tblItems.setItems(items);            // hand the list to the table once
}

ရိုးရိုး ArrayList တစ်ခု ရှိပြီးသားဆိုရင် line တစ်ကြောင်းတည်းနဲ့ ObservableList ထဲ ထုပ်ပါ:

ObservableList<Item> items = FXCollections.observableArrayList(myArrayList);
tblItems.setItems(items);

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

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

  • Item object တွေကို ကိုယ့်ဒေတာကနေ တည်ဆောက်ပါ: ရိုက်ထည့်ထားတဲ့ တန်ဖိုးတွေ၊ load လုပ်ထားတဲ့ file ဒါမှမဟုတ် database query။
  • အကြိမ်တိုင်း list အသစ် တည်ဆောက်မယ့်အစား ObservableList တစ်ခုတည်းကို table ရဲ့ ဒေတာအဖြစ် ထားပြီး အဲဒီထဲကို ထပ်ထည့်ပါ။

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

  • setItems(...) ကို တစ်ကြိမ်ပဲ ခေါ်ဖို့ လိုပါတယ်။ အဲဒီနောက် list ကို ပြောင်းရင် table က သူ့ဘာသာ update ဖြစ်ပါတယ် (နောက် recipe ကို ကြည့်ပါ)။
  • Table က စောင့်ကြည့်မယ့် list အတွက် FXCollections.observableArrayList(...) ကို သုံးပါ။ setItems(...) က ObservableList ကိုပဲ လက်ခံလို့ ရိုးရိုး ArrayList တစ်ခုကို အဲဒီမှာ ပေးရင် compile (code တစ်ခုလုံးကို ကြိုတင် ဘာသာပြန်ခြင်း) မဖြစ်ပါဘူး။ FXCollections.observableArrayList(myArrayList) က ကိုယ့် list ကို copy ကူးယူတာ ဖြစ်လို့ အဲဒီနောက်ပိုင်း item တွေကို ObservableList အသစ်ထဲမှာပဲ ထည့်၊ ဖယ်ပါ: မူလ ArrayList ကို ပြောင်းတာက table ဆီ မရောက်ပါဘူး။

တွဲသုံးလို့ရတဲ့ recipe များ: Table ကို ဒေတာနဲ့ ကိုက်ညီအောင် update လုပ်ထားခြင်း၊ Save and load text (စာသားကို save လုပ်ခြင်းနဲ့ ပြန် load လုပ်ခြင်း)။


User နှိပ်လိုက်တဲ့ row ကို သိအောင် လုပ်ခြင်း

ဒါက ဘာလုပ်ပေးလဲ: user ရွေးထားတဲ့ row ရဲ့ object ကို ဖတ်ပေးပါတယ်။ ဒါကြောင့် အဲဒီ object ကို ပြင်တာ၊ ဖျက်တာ ဒါမှမဟုတ် သူ့ အသေးစိတ်ကို ပြတာ လုပ်လို့ ရပါတယ်။

ကိုယ့် IA မှာ ဘယ်အခါ သုံးမလဲ: “ကိုယ် နှိပ်ထားတဲ့ row” ပေါ်မှာ အလုပ်လုပ်တဲ့ Edit ဒါမှမဟုတ် Delete button အတွက် သုံးပါ၊ ရွေးထားတဲ့ record ရဲ့ အသေးစိတ်ကို panel (screen ပေါ်က အကွက်) တစ်ခုမှာ ပြတဲ့အခါလည်း သုံးပါ။

SceneBuilder ထဲမှာ (layout): ရွေးထားတာပေါ်မှာ အလုပ်လုပ်မယ့် button ကို ထည့်ပြီး သူ့ onAction (button နှိပ်ရင် run မယ့် method ကို သတ်မှတ်တဲ့ setting) ကို handleEdit လို့ သတ်မှတ်ပါ။ Table က ရှိပြီးသား tblItems ပါပဲ။

<Button text="Edit" onAction="#handleEdit" />

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

@FXML
private void handleEdit() {
    Item selected = tblItems.getSelectionModel().getSelectedItem();
    if (selected == null) {
        // nothing is selected; tell the user and stop
        return;
    }
    // your IA logic here: use the selected row
    openEditScreen(selected);
}

ကိုယ်ပိုင် logic ကို ဘယ်မှာ ထည့်ရမလဲ: // your IA logic here လို့ မှတ်ထားတဲ့ line ပါ၊ row တစ်ခုကို ရွေးထားမှ run ပါတယ်။ ရွေးထားတာကို ဖတ်တာနဲ့ null (ဘာ object ကိုမှ မညွှန်းတဲ့ တန်ဖိုး) ဟုတ်မဟုတ် စစ်တာက ပြန်သုံးလို့ရတဲ့ wiring ပါ။

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

  • getSelectedItem() က အဲဒီ row ရဲ့ object အပြည့်ကို return (ရလဒ်အဖြစ် ပြန်ပေး) လုပ်လို့ getter တွေကနေတစ်ဆင့် field တိုင်းကို ယူလို့ ရပါတယ်။
  • openEditScreen(selected) ကို ရွေးထားတဲ့ row နဲ့ ကိုယ် လုပ်ချင်တဲ့ အလုပ် ဘာပဲဖြစ်ဖြစ် အဲဒါအဖြစ် ပြောင်းပါ။

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

  • onAction မှာ ပေးထားတဲ့ နာမည်နဲ့ method (handleEdit) က controller ထဲမှာ ရှိရပါမယ်။ မရှိရင် screen က load မဖြစ်ပါဘူး။
  • ဘာမှ ရွေးမထားရင် null ကို return လုပ်လို့ ရလဒ်ကို မသုံးခင် null ဟုတ်မဟုတ် အမြဲ စစ်ပါ။ ဒီအဆင့်ကို ကျော်လိုက်တာက Delete button မှာ crash (program ရုတ်တရက် ပျက်ပြီး ရပ်သွားခြင်း) ဖြစ်တဲ့ အဖြစ်များဆုံး အကြောင်းရင်းပါ။
  • Default (သတ်မှတ်မထားရင် သုံးတဲ့) အနေနဲ့ user က တစ်ကြိမ်မှာ row တစ်ခုပဲ ရွေးလို့ ရပါတယ်၊ IA app အများစု လိုချင်တာလည်း ဒါပါပဲ။

တွဲသုံးလို့ရတဲ့ recipe များ: Ask before doing something destructive (ပြန်ပြင်လို့ မရတဲ့ အလုပ် မလုပ်ခင် user ကို မေးခြင်း)၊ Pass information between screens (screen တွေကြား အချက်အလက် ပို့ခြင်း)။


Table ကို ဒေတာနဲ့ ကိုက်ညီအောင် update လုပ်ထားခြင်း

ဒါက ဘာလုပ်ပေးလဲ: table ရဲ့ နောက်ကွယ်က ObservableList ကို ပြောင်းပြီး table ကို refresh (အသစ် ပြန်ပြ) လုပ်ပါတယ်။ Table က အဲဒီ list ကို စောင့်ကြည့်နေလို့ screen ပေါ်မှာ ပြတာက သူ့ဘာသာ လိုက်ပြောင်းပါတယ်။

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

SceneBuilder ထဲမှာ (layout): ပြောင်းလဲမှုတွေကို စတင်ပေးမယ့် button တွေ (Add၊ Delete၊ Clear) ကို ထည့်ပြီး onAction တစ်ခုစီကို handler (button နှိပ်တာလို event ဖြစ်တဲ့အခါ run တဲ့ code) တစ်ခုစီနဲ့ ချိတ်ပါ။ Table ကတော့ tblItems ပါပဲ။

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

// Add a row: it appears immediately.
// your IA logic here: build the new object from your inputs
items.add(new Item("Milk", 2));

// Remove the selected row.
Item selected = tblItems.getSelectionModel().getSelectedItem();
if (selected != null) {
    items.remove(selected);
}

// Clear the whole table.
items.clear();

ကိုယ်ပိုင် logic ကို ဘယ်မှာ ထည့်ရမလဲ: // your IA logic here လို့ မှတ်ထားတဲ့ line ပါ၊ အဲဒီမှာ ထည့်မယ့် object ကို ကိုယ့် input (program ထဲ ထည့်ပေးတဲ့ ဒေတာ) တွေကနေ တည်ဆောက်ပါ။ List ထဲ ထည့်တာ၊ list ထဲက ဖယ်တာနဲ့ list ကို ရှင်းတာတွေက ပြန်သုံးလို့ရတဲ့ wiring ပါ။

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

  • setItems(...) ကို ပေးခဲ့တဲ့ ObservableList တစ်ခုတည်းပေါ်မှာပဲ ထည့်တာ၊ ဖယ်တာ၊ ရှင်းတာ လုပ်ပါ။ setItems ကို ထပ်ခေါ်စရာ မလိုပါဘူး။

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

  • ဒါ အလုပ်ဖြစ်တာက list ကိုယ်တိုင်ကို ပြောင်းနေလို့ပါ။ List အသစ်စက်စက် တစ်ခု တည်ဆောက်ရင် table က အဲဒီ list အကြောင်း သိအောင် setItems(...) ကို ထပ်ခေါ်ရပါမယ်။
  • ရှိပြီးသား object တစ်ခု ထဲက တန်ဖိုးကို ပြောင်းတာ (ဥပမာ ပမာဏကို object ထဲမှာပဲ တိုးလိုက်တာ) က cell (ဇယားကွက်ထဲက အကွက်) ကို အမြဲ refresh မလုပ်ပေးပါဘူး၊ ဘာလို့လဲဆိုတော့ table က အဲဒီ တန်ဖိုးကို တစ်ကြိမ်ပဲ ဖတ်ခဲ့လို့ပါ။ ဒီလို ပြင်ပြီးရင် tblItems.refresh() ကို ခေါ်ပါ၊ ဒါမှမဟုတ် object ကို ဖယ်ပြီး ပြန်ထည့်ပါ။

တွဲသုံးလို့ရတဲ့ recipe များ: ကိုယ့်ဒေတာနဲ့ table ကို ဖြည့်ခြင်း၊ User စာရိုက်နေစဉ် table ကို filter လုပ်ခြင်း၊ Save and load text (စာသားကို save လုပ်ခြင်းနဲ့ ပြန် load လုပ်ခြင်း)။


User စာရိုက်နေစဉ် table ကို filter လုပ်ခြင်း

ဒါက ဘာလုပ်ပေးလဲ: ရှာဖို့ box ထဲမှာ user ရိုက်တာနဲ့ ကိုက်တဲ့ row တွေကိုပဲ ပြပြီး key တစ်ချက် နှိပ်တိုင်း update လုပ်ပါတယ်။ ရိုးရိုး list တစ်ခုအတွက်လည်း ဒီနည်းအတိုင်းပဲ အလုပ်လုပ်ပါတယ်။

ကိုယ့် IA မှာ ဘယ်အခါ သုံးမလဲ: client က scroll မလုပ်ဘဲ record တစ်ခုကို မြန်မြန် ရှာတွေ့အောင် table ရှည်ရှည် တစ်ခုရဲ့ အပေါ်မှာ ရှာဖို့ box တစ်ခု ထားတဲ့အခါ သုံးပါ။

SceneBuilder ထဲမှာ (layout): table ရဲ့ အပေါ်မှာ TextField (စာ တစ်ကြောင်း ရိုက်ထည့်တဲ့ box) တစ်ခု ထည့်ပြီး txtSearch ဆိုတဲ့ fx:id ပေးပါ။ Table ကတော့ tblItems ပါပဲ။

<TextField fx:id="txtSearch" promptText="Search..." />

Controller ထဲမှာ (.java file): ဒေတာ အပြည့်ကို list တစ်ခုထဲမှာ ထားပြီး ကိုက်တဲ့ row တွေပဲ ပါတဲ့ ပိုတိုတဲ့ list ကို table ကို ပေးပါ။ ဒီမှာ ကိုက်မကိုက် စစ်တာက ကိုယ်တိုင် ရေးထားတဲ့ loop (ထပ်ခါထပ်ခါ run တဲ့ code အပိုင်း) တစ်ခုပါ၊ ကိုယ် သိပြီးသား ရှာနည်းနဲ့ loop ပတ်နည်းပေါ်မှာ အခြေခံထားပါတယ်။

Import line များ:

import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

Controller ထဲမှာ:

@FXML private TextField txtSearch;

// allItems is the full data; the table shows whichever rows match.
private final ObservableList<Item> allItems = FXCollections.observableArrayList();

@FXML
public void initialize() {
    // ... column setup, then fill allItems ...
    tblItems.setItems(allItems);

    // Re-filter every time the search text changes.
    txtSearch.textProperty().addListener((obs, oldText, newText) -> applyFilter(newText));
}

private void applyFilter(String query) {
    String needle = query.toLowerCase().trim();
    ObservableList<Item> matches = FXCollections.observableArrayList();
    for (int i = 0; i < allItems.size(); i++) {
        Item item = allItems.get(i);
        // your IA logic here: decide what counts as a match
        if (item.getName().toLowerCase().contains(needle)) {
            matches.add(item);
        }
    }
    // for-each version: for (Item item : allItems) { ... }
    tblItems.setItems(matches);
}

ကိုယ်ပိုင် logic ကို ဘယ်မှာ ထည့်ရမလဲ: // your IA logic here လို့ မှတ်ထားတဲ့ if condition (မှန်လား မှားလား စစ်တဲ့ အခြေအနေ) ပါ၊ အဲဒီမှာ ဘာကို ကိုက်တယ်လို့ သတ်မှတ်မလဲ ဆုံးဖြတ်ပါ။ Listener (တန်ဖိုး တစ်ခု ပြောင်းတိုင်း JavaFX က run ပေးတဲ့ code) နဲ့ loop က ပြန်သုံးလို့ရတဲ့ wiring ပါ။

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

  • if condition ကို ကိုယ့် user တွေ ရှာမယ့် field နဲ့ ကိုက်အောင် ပြောင်းပါ၊ ဒါမှမဟုတ် field အများကို တစ်ပြိုင်နက် စစ်အောင် ပြောင်းပါ။
  • contains က “စာသားထဲ ဘယ်နေရာမှာမဆို” ပါရင် ကိုက်တယ်လို့ စစ်ပါတယ်။ စာသားရဲ့ အစမှာ ကိုက်မှ ရွေးချင်ရင် startsWith ကို သုံးပါ။
  • နှစ်ဘက်လုံးမှာ toLowerCase() ကို သုံးတာက ရှာတဲ့အခါ စာလုံး အကြီး၊ အသေးကို ဂရုမစိုက်အောင် လုပ်ပေးပါတယ်။

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

  • fx:id txtSearch က @FXML field နာမည်နဲ့ အတိအကျ ကိုက်ရပါမယ်။ မကိုက်ရင် screen က load မဖြစ်ပါဘူး။
  • allItems ကို မထိမပြင်ရတဲ့ မူရင်း list အပြည့်အဖြစ် ထားပြီး matches ကို အဲဒီ list ကနေပဲ တည်ဆောက်ပါ။ မူရင်း list ကိုယ်တိုင်ထဲက row တွေကို ဖယ်ပြီး filter လုပ်ရင် ဖျောက်လိုက်တဲ့ row တွေ ပြန်ရမှာ မဟုတ်ပါဘူး။
  • Listener က lambda (နာမည် မပါတဲ့ method အတိုလေး) တစ်ခုကို သုံးပါတယ် ((obs, oldText, newText) -> ... အပိုင်း)။ Lambda က IB စာမေးပွဲမှာ စစ်တဲ့ Java အပိုင်းထဲမှာ မပါပေမဲ့ text field တစ်ခုကို စောင့်ကြည့်ဖို့ ပုံမှန် သုံးတဲ့ နည်းပါ။
  • JavaFX မှာ ဒီအလုပ်ကို ကိုယ်တိုင် loop ရေးစရာ မလိုဘဲ လုပ်ပေးတဲ့ အသင့်ပါ FilteredList လည်း ရှိပါတယ်။ Algorithm (အယ်လ်ဂိုရီသမ်၊ ပြဿနာကို အဆင့်ဆင့် ဖြေရှင်းတဲ့ နည်းလမ်း) ကို မြင်သာအောင် loop ကို အရင် ပြထားတာပါ၊ ကျွမ်းကျင်လာရင် FilteredList ကို သုံးကြည့်ပါ။

တွဲသုံးလို့ရတဲ့ recipe များ: React to the Enter key (Enter key ကို တုံ့ပြန်ခြင်း)၊ Table ကို ဒေတာနဲ့ ကိုက်ညီအောင် update လုပ်ထားခြင်း။