July 22, 2013

Day 3 Layout of User Interface

Application များအား ရေးသားရာတွင် User Interface ၏ Design သည် လွန်စွာအရေးကြီးပါသည်။ အသုံးပြုသူသည် Application ၏ အသုံးဝင်ပုံကို နားမလည်ခင် ပြင်ပအမြင် Design ဖြင့် ဦးစွာ Application ၏ တန်ဖိုးအား သတ်မှတ်မည် ဖြစ်သည်။ ယနေ့တိုင် Java ၏ UI Design များသည် ကောင်းလှသည်ဟု မဆိုနိုင်ပါ။ Swing သည် အခြားသော Flash နှင့် C# တို့ဖြင့် ရေးသားထားသော Application များလောက် လှပခြင်း မရှိသည်ကို တွေ့ရပါသည်။ အလားတူပင် Servlet, JSP အစရှိသော Application များသည်လည်း PHP ဖြင့် ရေးသားထားသော Application များလောက် စိတ်ကို ဖမ်းစားနိုင်စွမ်း မရှိပါ။ အကြောင်းအရင်းများစွာ ရှိပါသည်။

အချို့ကပြောကြပါသည်။ Java Developer များသည် Design အပိုင်းကို စိတ်မဝင်စားပဲ Business Logic နှင့် Technology ကိုသာ အဓိကထားသောကြောင့် ဖြစ်သည်ဟု ဆိုကြပါသည်။ ကျွှန်တော်ကတော့ Java ကဲ့သို့ သော Language ဖြင့် Design ကို ရေးသားရန် မလွယ်ကူသောကြောင့် ဖြစ်သည်ဟု ထင်ပါသည်။ Getter Setter များကို အသုံးပြုလေ့ရှိသော Java ဖြင့် Design များအား ရေးသားရန်၊ အလွယ်တကူ ပြောင်းလည်းရန် လွန်စွာခက်ခဲပါသည်။ ထို့အပြင် UI Component များ၏ ဖွဲ့စည်းပုံကိုလည်း နားလည်ရန် ခက်ခဲလှပါသည်။

ယခု JavaFX သည် UI ၏ ဖွဲ့စည်းပုံအား Java ဖြင့်သာမက XML အား အခြေခံသော FXML ဖြင့်လည်း ရေးသားနိုင်ပါသည်။ ထို့အပြင် FXML အား Visually Edit ပြုလုပ်နိုင်သော Scene Builder သည်လည်း  အသုံးပြုရလွယ်ကူ၍ အခမဲ့ အသုံးပြုနိုင်ပါသည်။ ထိုထက်မက CSS ကို အသုံးပြု၍လည်း ရေးသားထားသော UI Component များ၏ ဒီဇိုင်းကို လိုအပ်သလို လွယ်ကူစွာ ပြုပြင် ရေးသားလာနိုင်၏။ JavaFX အား အသုံးပြုရန် အချိန်ကျရောက်ပြီ ဖြစ်သည်။

ယခုတစ်ခေါက် ဘလောဂ်တွင် ဒီဇိုင်းတွင် မရှိမဖြစ်လိုအပ်သော Layout အကြောင်းကို Scene Builder အား အသုံးပြု၍ ဖော်ပြသွားပါဦးမည်။


Layout


Design လောကတွင် Layout, Color, Font အစရှိသည်တို့သည် လွန်စွာမှ အရေးကြီးလှပါသည်။ အသုံးပြုမည့် Contents များ၏ အထားအသို၊ အကြီးအသေး အစရှိသည်တို့ကို သတ်မှတ်ပေးသည်မှာ Layout ဖြစ်၏။ User Interface တွင် ပါဝင်သည့် Contents များ၏ အရောင်များဖြင့်လည်း  အသုံးပြုသူ၏ စိတ်နှလုံးအား ဖမ်းစားနိုင်သည်။ Application ၏ Concept ကိုလည်း အများကြီး ပြောင်းလည်း ပစ်နိုင်၏။ အသုံးပြုမည့် စာလုံးများ၏ ဒီဇိုင်း၊ အကြီးအသေး အစရှိသည်တို့ကို လိုအပ်သလို ပြောင်းလည်း အသုံးပြုခြင်းဖြင့် မိမိ၏အပလီကေးရှင်းအား အသုံးပြုသူ၏ စိတ်ထဲသို့ တိုက်ရိုက် ပေးပို့နိုင်ပါသည်။

JavaFX တွင် Developer များက အဆင်သင့် အသုံးပြုနိုင်ရန် Layout များအား Container များတွင် Layout Pane များ အနေဖြင့် အသင့်ပြင်ထားပါသည်။ ၎င်းတို့မှာ အောက်ပါအတိုင်း ဖြစ်ကြသည်။


JavaFX တွင် အသုံးပြုနိုင်သော Container များမှာအောက်ပါအတိုင်းဖြစ်ပါသည်။
  • Group
    Node များအား စုဝေး၍ အသုံးပြုနိုင်သော Container ဖြစ်ပါသည်။ Layout အဖြစ်အသုံးပြုနိုင်ခြင်း မရှိပါ။ ထို့ကြောင့် javafx.scene ၏ အောက်တွင် တည်ရှိပါသည်။ အခြားသော Container များမှာ Layout အဖြစ်အသုံးပြုနိုင်သောကြောင့် javafx.scene.layuot ၏ အောက်တွင် ထားရှိပါသည်။
  • FlowPane
    Node များအား ဘယ်မှညာ၊ ဒါမှမဟုတ် ညာမှဘယ်သို့ ရိုးရှင်းစွာ နေရာချထားရာတွင် အသုံးပြုနိုင်ပါသည်။
  • Hbox
    Node များအား အလျားလိုက် နေရာချထားရာတွင် အသုံးပြုနိုင်ပါသည်။
  • Vbox
    Node များအား ဒေါင်လိုက် နေရာချထားရာတွင် အသုံးပြုနိုင်ပါသည်။
  • BorderPane
    Top, Bottom, Left, Right နှင့် Center ဟု နေရာငါးမျိုးဖြင့် နေရာချထားပေးနိုင်သော Container ဖြစ်ပါသည်။
  • AnchorPane
    Node တစ်ခုနှင့် တစ်ခု၏ အစွန်းများ၏ အကွာအဝေးကို သတ်မှတ်ခြင်းအားဖြင့် နေရာချထားပေးနိုင်သော Container ဖြစ်ပါသည်။
  • StackPane
    Node များအား တစ်ခုနှင့်တစ်ခု ထပ်ဆင့်ကာ နေရာချထားပေးနိုင်ပါသည်။ Swing ၏ CardLayout နှင့် ခပ်ဆင်ဆင်တူပါသည်။
  • TilePane
    Node များအား တူညီသော Size အဖြစ် နေရာချရန် လိုအပ်သည့်အခါမျိုးတွင် အသုံးပြုနိုင်ပါသည်။
  • GridPane
    Node များအား ဇယားအတွင်း နေရာချရာတွင် အသုံးပြုနိုင်ပါသည်။
အချို့သော Container များအား Scene Builder အား အသုံးပြု၍ ရေးသားကြည့်ပါဦးမည်။

Border Pane


BorderPane သည် JavaFX တွင် Built In အနေဖြင့် ပါဝင်သော Layout တစ်မျိုးဖြစ်ပြီး၊ Swing ၏ BorderLayout နှင့် ဆင်တူပါသည်။ ၎င်းတွင် Region ၅ခု ပါဝင်ပြီး၊ Top, Bottom, Left, Right နှင့် Center တို့ဖြစ်ကြ၏။  အဆိုပါ Region အသီးသီး၏ Size ကိုလည်း လိုအပ်သလို သတ်မှတ်နိုင်ပြီး၊ အသုံးပြုရန် မလိုအပ်ပါက မရေးသားပဲ နေနိုင်ပါသည်။ BorderPane သည် အခြေခံ Window GUI တစ်ခုအား တည်ဆောက်ရာတွင် အသုံးဝင်ပါသည်။ Top နေရာအား Tool Bar အဖြစ် ထားရှိပြီး၊ Left နေရာတွင် Navigation၊ Bottom တွင် Status Bar၊ ညာဘက်တွင် Additional Information နှင့် Center နေရာတွင် Contents များကို ထားရှိ အသုံးပြုနိုင်ပါသည်။

အောက်ပါပုံတွင် အခြေခံ Layout အဖြစ် BorderPane အား အသုံးပြုထားပါသည်။ အထက်ဆုံး Region တွင် HBox အား အသုံးပြုထားပြီး ၎င်းတွင် Button ၃ခုကို နေရာချထားပါသည်။ တဖန် Bottom Region တွင် TabPane အား ဖြည့်စွက်ထားပါသည်။ ထို့နောက် Left Region တွင် Accordion အား၎င်း၊ Right Region တွင် VBox ကို၎င်း၊ Center Region တွင် StakePane အား၎င်း ဖြည့်စွက် ရေးသားထားပါသည်။

Layout များအား ရေးသားရာတွင် Java ဖြင့် တိုက်ရိုက်ရေးသားနိုင်သော်လည်း Scene Builder အား အသုံးပြုပါက Component များအား Drug And Drop လုပ်ရုံဖြင့် လိုအပ်သည်များကို ရေးသားနိုင်ပါသည်။ Size များနှင့် နောက်ခံ အရောင်များအား သတ်မှတ်ရာတွင်လည်း FXML ၏ Attribute များတွင် တိုက်ရိုက်ရေးသား၍သော်၎င်း Scene Builder ၏ Properties များအား သတ်မှတ်၍သော်၎င်း ရေးသားနိုင်ပါသည်။ Scene Builder ကို အသုံးပြု၍ ရေးသားသည်မှာ အလွယ်ကူဆုံး နည်းလမ်း ဖြစ်ပါသည်။


HBox


HBox သည် အလျားလိုက် Component များအား နေရာချထားရာတွင် အသုံးပြုနိုင်သော Layout တစ်မျိုး ဖြစ်ပါသည်။ HBox တွင် နောက်ခံအရောင်(Background Color)၊ အနားနှင့် Component များအကြားရှိ အကွာအဝေး (Padding)၊ Component များအကြားရှိ အကွာအဝေး(Space)တို့ကို သတ်မှတ်နိုင်ပါသည်။

 ဦးစွာ ဘယ်ဘက် Library အတွင်းရှိ HBox အား Drag လုပ်လာ၍၊ BorderPane ၏ Top Region တွင် နေရာချထားပါသည်။ ပြီးပါက ၎င်း၏ အလျားအနံအား Drag And Drop လုပ်ကာ သင့်တော်သလို ညှိ၏။ ပြီးလျှင် ညာဘက်ရှိ Spacing တွင် 5 ကို ဖြည့်စွက်လိုက်ပါသည်။ Padding ကို အသုံးပြုလိုပါက အသီးသီး သတ်မှတ်ရေးသားနိုင်ပါသည်။ ဤနေရာတွင် အသုံးပြုရန် မလိုအပ်ပါသဖြင့် Default အတိုင်း 0 အဖြစ်ထားပါသည်။ နောက်ဆုံးတွင် Button အား Drag လုပ်ကာ HBox အပေါ်တွင် နေရာချပါသည်။


VBox


VBox Layout Pane သည် HBox နှင့် ဆင်တူသော Layout Pane တစ်ခု ဖြစ်ပြီး၊ ပါဝင်သော Node များအား ဒေါင်လိုက်နေရာချထားရာတွင် အသုံးပြုနိုင်ပါသည်။ VBox သည်လည်း HBox အလားတူ၊ Background Color, Padding နှင့် Spacing တို့အား သတ်မှတ်နိုင်ပါသည်။



FlowPane


FlowPane သည် ပါဝင်သည့် Node များအား အစီအစဉ်အလိုက် နေရာချထားရာတွင် အသုံးပြုပါသည်။ စီစဉ်ရာတွင်လည်း အလျားလိုက်သော်၎င်း ဒေါင်လိုက်သော်၎င်း သတ်မှတ်၍ စီစဉ် နေရာချနိုင်ပါသည်။ နေရာချရာတွင် Pane ၏ နေရာကုန်သွားရာတွင် နောက်တစ်ကြောင်းကို ချ၍ စီစဉ်သွားမည် ဖြစ်ပါသည်။ Swing ၏ FlowLayout နှင့် ဆင်တူပါသည်။ FlowPane အသုံးပြုပုံအား ရေးသားကြည့်ပါမည်။
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class FlowLayoutSample extends Application {

 @Override
 public void start(Stage primaryStage) {
  
  FlowPane pane = new FlowPane();
  pane.setPrefSize(400, 200);
  
  for(int i=0; i<10; i++) {
   pane.getChildren().add(new Button("Button" + i));
  }
  Scene scene = new Scene(pane);

  primaryStage.setScene(scene);
  primaryStage.show();
 }

 public static void main(String[] args) {
  launch(args);
 }
}
အထက်ပါအတိုင်း FlowPane အား ရေးသား၍ Java Application အနေဖြင့် Run ကြည့်ပါမည်။

ဘယ်မှ ညာသို့ အလျားလိုက် Button များအား နေရာချသွားသည်ကို တွေ့ရပါသည်။  Padding များ Spacing များ မပါသောကြောင့် ကြည့်ရသည်မှာ အစဉ်မပြေပါ။ Spacing နှင့် Padding တို့ကို ဖြည့်စွက်ကြည့်ပါမည်။
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class FlowLayoutSample extends Application {

 @Override
 public void start(Stage primaryStage) {
  
  FlowPane pane = new FlowPane();
  pane.setPrefSize(400, 200);
  pane.setPadding(new Insets(10));
  pane.setHgap(10);
  pane.setVgap(5);
  
  for(int i=0; i<10; i++) {
   pane.getChildren().add(new Button("Button" + i));
  }
  Scene scene = new Scene(pane);

  primaryStage.setScene(scene);
  primaryStage.show();
 }

 public static void main(String[] args) {
  launch(args);
 }
}

အထက်ပါအတိုင်း စာကြောင်း နံပါတ် ၁၅၊ ၁၆၊ ၁၇ တွင်ဖော်ပြထားသည့်အတိုင်း padding နှင့် Gap တို့အား သတ်မှတ်ရေးသားပေးပါက အောက်ပါအတိုင်း Space နှင့် Padding များအား ဖော်ပြပေးနိုင်ကြောင်း တွေ့ရပါသည်။



StackPane


StackPane သည် အတွင်းရှိ Node များအား ထပ်ဆင့် ဖော်ပြနိုင်သော ထူးခြားချက်ကို ပိုင်ဆိုင်ပါသည်။ StackPane အတွင်း Node များအား တစ်ခုစီ ဖြည့်စွက်သွားပါက၊ ဦးစွာ ဖြည့်စွက်ထားသော Node အား အောက်ဆုံးတွင် ဖော်ပြ၍ နောက်ဆုံး ဖြည့်စွက်သော Node အား အပေါ်ဆုံးတွင် ဖော်ပြနိုင်မည် ဖြစ်ပါသည်။ ဤကဲ့သို့သော ထူးခြားချက်အား အသုံးပြု၍ StackPane အား Swing ၏ CardLayout ကဲ့သို့ အသုံးပြုနိုင်ပါသည်။

နမှုနာတစ်ခုကို ရေးသားကြည့်ပါမည်။ images အမည်ရှိ Folder အတွင်းတွင် Image လေးခုကို ဖြည့်စွက်ထားပြီး၊ BorderPane ၏ ဘယ်ဘက်တွင် Image များ၏ Path အား ဖော်ပြပြီး၊ ၎င်းတို့အား တစ်ခုချင်း ရွေးချယ်ပါက Center တွင် ListView အတွင်း ရွေးချယ် ထားသော Image များအား ဖော်ပြနိုင်သော အပလီဖြစ်ပါသည်။ Swing ကို အသုံးပြုပါက CardLayout အား အသုံးပြုမည် ဖြစ်သော်လည်း JavaFX တွင် StackPane အား အသုံးပြုသွားမည် ဖြစ်ပါသည်။

Stack.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane prefHeight="240.0" prefWidth="360.0"
 xmlns:fx="http://javafx.com/fxml">

 <center>
  <StackPane prefHeight="240.0" prefWidth="240.0"
   style="-fx-background-color : white;" fx:id="stack" />
 </center>
 <left>
  <VBox prefHeight="240.0" prefWidth="120.0"
   style="-fx-background-color : #977C7C;" fx:id="vbox" />
 </left>
</BorderPane>

Main.java
package com.dtc.stack;

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

 private Scene scene;

 @Override
 public void start(Stage primaryStage) throws IOException {

  Parent root = FXMLLoader.load(getClass().getResource("Stack.fxml"));
  scene = new Scene(root);

  this.setViewData();

  primaryStage.setScene(scene);
  primaryStage.setTitle("Stack Pane Sample");
  primaryStage.show();
 }

 private void setViewData() throws IOException {

  Path images = Paths.get("images");
  if (Files.isDirectory(images, LinkOption.NOFOLLOW_LINKS)) {
   DirectoryStream<Path> dir = Files.newDirectoryStream(images);
   final ObservableList<Path> data = FXCollections.observableArrayList();
   final StackPane stack = (StackPane) scene.lookup("#stack");
   for (Path image : dir) {
    data.add(image);
   }
   stack.getChildren().add(getImageView(data.get(0)));
   
   final ListView<Path> listView = new ListView<>(data);
   listView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
   listView.getSelectionModel().selectFirst();
   listView.getSelectionModel().selectedItemProperty()
     .addListener(new ChangeListener<Path>() {

      @Override
      public void changed(
        ObservableValue<? extends Path> ov,
        Path old_value, Path new_value) {
       try {
        stack.getChildren().clear();
        stack.getChildren().add(getImageView(new_value));
       } catch (IOException e) {
        e.printStackTrace();
       }
      }
     });

   VBox vbox = (VBox) scene.lookup("#vbox");
   vbox.getChildren().add(listView);
  }

 }

 private final Node getImageView(Path image) throws IOException {
  ImageView view = new ImageView(new Image(Files.newInputStream(image)));
  return view;
 }

 public static void main(String[] args) {
  launch(args);
 }
}
အထက်ပါ Main.java အတွင်းရှိ စာကြောင်း နံပါတ် ၅၀တွင် FXML ဖိုင်အတွင်းရှိ Node များအား Scene Object ဖြင့် ရှာဖွေနိုင်သည်ကို တွေ့ရပါသည်။ FXML အတွင်းတွင် fx:id ကို ရေးသားထားပါက၊ Scene#lookup ဖြင့် အဆိုပါ Node အား ရှာဖွေနိုင်ပါသည်။ ဤနမှုနာအတွင်းတွင် ListView ကဲ့သို့သော Controller နှင့် ImageView ကဲ့သို့သော Image များကို အသုံးပြုထားသော်လည်း Layout အကြောင်းကိုသာ အဓိကထား၍ ဖော်ပြလိုသောကြောင့် နောက်ဘလောဂ်များဖြင့် ဆက်လက်ဖော်ပြသွားပါမည်။ ဤနမှုနာအတွင်းတွင် Scene အား ကနဦးဖော်ပြရာတွင် (စာကြောင်း နံပါတ် ၅၄) ပဌမဦးဆုံး Image အား StackPane ၏ children အတွင်းတွင် ဖြည့်စွက် ဖော်ပြပါသည်။ တဖန် ListView ၏ Item အား ပြောင်းလည်း ရွေးချယ်ရာ၌ StackPane ၏ Children အတွင်းရှိ Node များအား Clear လုပ်၍၊ ရွေးချယ်ထားသော Image အား အသစ်ပြန်လည် ဖြည့်စွက်ထားပါသည် (စာကြောင်း နံပါတ် ၆၇နှင့် ၆၈)။

ဤနည်းအားဖြင့် ListView အတွင်းရှိ Node များအား ပြောင်းလည်း ရွေးချယ်ပါက StackPaneအတွင်းရှိ ImageView အားသင့်လျှော်သလို ပြောင်းလည်းဖော်ပြအောင် ရေးသားနိုင်ပါသည်။

နမှုနာအား Runကြည့်သောအခါ အောက်ပါအတိုင်းဖော်ပြနိုင်သည်ကို တွေ့ရပါသည်။

duke1.jpg duke2.jpg
duke3.jpg duke4.jpg
ဤနေ့ လေ့လာခြင်းတွင် JavaFX ၏ Layout များအကြောင်းကို လေ့လာခဲ့ပါသည်။ နောက်ရက်များတွင် ဆက်လက်၍ Controller များအကြောင်းကို လေ့လာသွားပါဦးမည်။

ဆက်ပါဦးမည်။ လေးစားစွာဖြင့်
မင်းလွင်

No comments:

Post a Comment