Toggle Theme Editor
Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate Charcoal

Jfx View: Model View Controller With S W I N G And J F X - Part 4 -

Discussion in 'Java Update' started by Joe, 27/11/19.

  1. Joe

    Joe Thành viên VIP

    (Continue of Model View Controller With S W I N G And J F X - Part 3 - )

    Before I go into details with JFX let me summarize the parallels between SWING-MVC and JFX.
    PHP:
    Structural view
    +-----------------+---------------------------+----------------------------+
    !                 !          
    SWING            !           JFX              !
    +-----------------+---------------------------+----------------------------+
    !  
    Model          plain text with XML       FXML bases on XML          !
    !                 ! 
    syntax (case sensitive)   !                            !
    +-----------------+---------------------------+----------------------------+
    !  
    View           conventional JAVA         ! as Extension of the        !
    !                 !                           ! 
    Application API            !
    +-----------------+---------------------------+----------------------------+
    !  
    Controller     instantiated by View      instantiated by FMXLLoader !
    +-----------------+---------------------------+----------------------------+
     
    Technical view
    +-----------------+---------------------------+----------------------------+
    !                 !          
    SWING            !           JFX              !
    +-----------------+---------------------------+----------------------------+
    !  
    Model          shortened J-Components as ! JFX components in          !
    !                 ! 
    keywords:Label for JLabel javafx package             !
    !                 ! 
    etc.                      !                            !
    +-----------------+---------------------------+----------------------------+
    !  
    View           run ModelLoader to load   run FXMLLoader to load the !
    !                 ! 
    model and to instantiate  model AND the controler    !
    !                 ! 
    the controller            !                            !
    +-----------------+---------------------------+----------------------------+
    !  
    Controller     ! use HashMap to access and ! use @FXML annotation to    !
    !                 ! 
    to refer SWING components access refer JFX comp.   !
    +-----------------+---------------------------+----------------------------+
    JFX Dependencies must be named in FXML model (e.gonAction="#click") and implemented
    in the controller 
    (see example). The interchanges happen with @FXML annotation.
    Joe SWING is free from such annotationThe dependencies are "directly" implemented
    without having to be named explicitly
    .
     
    Example
    +------------+-----------------------------------+---------------------------------+
    !            !          
    SWING                    !           JFX                   !
    +------------+-----------------------------------+---------------------------------+
    Model      ! <button>name=...........</button> ! <Button id:................. /> !
    +------------+-----------------------------------+---------------------------------+
    View       ModelLoader m=new ModelLoader(..) ! FXMLLoader f=new FXMLLoader(..) !
    !            ! 
    JFrame jf=m.load()                ! AnchorPane ap=f.load()          !
    +------------+-----------------------------------+---------------------------------+
    Controller ! public Controller(HashMap<String, ! @FXML Button but;               !
    !            !   
    Objectmapthrows Exception { ! ...                             !
    !            !    ...
    //get components            ! @FXML // dependency             !
    !            !   JButton b=(JButton)map.get(..); ! private void click() {          !
    !            !   
    b.addActionListener(e->{        !   ...                           !
    !            !        ...                        ! }                               !
    !            !   });                             ! ...                             !
    !            !   ...                             !                                 !
    +------------+-----------------------------------+---------------------------------+
    The technical view gives you the fundamental differences between self-implemented SWING MVC and Java FX MVC: the Dependency Injection and the instantiation of Controller.
    - JFX model and controller go in sync with an arrangement: the dependency must be known by the model (e.g. here: onAction="#click") and implemented by controller (e.g. here: private void click()). This tightly clutched arrangement makes the MVC rigid. Any correction or improvement must be done in the model and the controller.
    - I've removed this "rigidity" and let the controller the freedom independently to implement the dependency. Any change, for example actionListener to mouseListener, can be solely done in the controller -the model won't be changed.
    - FXMLLoader needs to know the "who's the controller" with the hint fx:controller="MyController" so that it could locate and instantiate it. And that causes an "impact" between model and controller: both must always go "together".
    - I move the instantiation out of the model so that the controller can be instantiated anywhere, but before the model is presented (showed) by "setVisible(true)". The "auto-instantiation" of FXMLLoader way can be done with the 2nd constructor of ModelLoader, too (see Part 3).
    PHP:
       // load model myModel.txt and the controller MyController
       
    ModelLoader ml = new ModelLoader(myModel.txt"MyController");
       
    JFrame jf ml.load();
    The JFX Structure
    [​IMG]
    (source: tutorialspoint.com)

    JFX structure shows 3 distinct layers which resemble a "worldly theater":

    - stage
    - scene
    - the show inside the scene

    The JFX View
    Unusually compared to "unJFX" java apps JFX app can be started either by the conventional way with the main() method, or directly with the start(). Example:

    Direct
    PHP:
    public class MyAppL extends Application {
      public 
    void start(Stage stage) { // Stage is by convention the parameter
        
    FXMLLoader fxml = new FXMLLoader(getClass().getResource("myFXML.fxml"));
        
    AnchorPane root fxml.load();
        ...
        
    stage.setScene(new Scene(root));
        
    stage.show();
      }
    }
    Indirect
    PHP:
    public class MyAppL extends Application {
      public static 
    void main(String... args){
        
    launch(args); // by convention
      
    }
      
    //
      
    public void start(Stage stage) { // Stage is by convention the parameter
        
    FXMLLoader fxml = new FXMLLoader(getClass().getResource("myFXML.fxml"));
        
    AnchorPane root fxml.load();
        ...
        
    stage.setScene(new Scene(root));
        
    stage.show();
      }
    }
    Some may say the "conventional way" with main() is safer, but it isn't proven that the first ways is unsafe. Probably the old habit is unconquerable. You may notice that the launch() method is started to "launch" the app. It's the convention and you have to "launch" the launch()

    JFX application is also driven by the method start(). If there's a "start" it must exist somewhere a stop(), too. Yes, it does exist. The JFX stop() method is always executed when JFX application terminates. Experienced JFX developers usually overwrite this method so that they can do the "clean-up" properly (e.g. DB closing/recovering, etc.) Example:
    PHP:
    public class MyAppL extends Application {
      public 
    void start(Stage stage) { // Stage is by convention the parameter
        
    FXMLLoader fxml = new FXMLLoader(getClass().getResource("myFXML.fxml"));
        
    AnchorPane root fxml.load();
        ...
        
    stage.setScene(new Scene(root));
        
    stage.show();
      }
      ...
      public 
    void stop() {
        
    // do the clean-up action
        
    Platform.exit(); // properly exit
      
    }
    }
    External parameters which are in many case packaged in a String array (String[] args) and by convention it is passed to the main( ) method (it's the C heritage). How does it work with JFX? You can do that in two ways:

    1) using a global intermediator:
    PHP:
    public class MyAppL extends Application {
      public static 
    void main(String... args){
        
    parms args// assign args to parms
        
    launch(parms); // by convention
      
    }
      
    // global parameters
      
    private static String[] parms;
      
    //
      
    public void start(Stage stage) { // Stage is by convention the parameter
        // parms[0] is the given fxml file name
        
    String fxml parms.length 0parms[0]:"myFXML.fxml";
        
    FXMLLoader fxml = new FXMLLoader(getClass().getResource(fxml));
        
    AnchorPane root fxml.load();
        ...
        
    stage.setScene(new Scene(root));
        
    stage.show();
      }
      ...
    }
    2) by JFX convention using the List<String> technique
    PHP:
    public class MyAppL extends Application {
      public 
    void start(Stage stage) {
        
    // this is the convention how external variables are passed to JFX app
        
    List<String> list = getParameters().getRaw();
        
    // the 1st element of List<String> is the fxml file name
        
    String fxml = list.size() > 0? list.get(0):"myFXML.fxml";
        
    FXMLLoader fxml = new FXMLLoader(getClass().getResource(fxml));
        
    AnchorPane root fxml.load();
        ...
        
    stage.setScene(new Scene(root));
        
    stage.show();
      }
      ...
    }
    Again, I prefer the 2nd way with the "List<String>". With the methods setX() and setY() for the Stage the view can be positioned anywhere on the screen. Example
    PHP:
        stage.setX(200);  // 200 on X axis relating to the upper left corner of the screen
        
    stage.setY(200);  // 200 on Y axis relating to the upper left corner of the screen
        
    stage.show();     // presenting the View
    (NEXT: the FXML Model)
     
    Last edited: 27/11/19

Chia sẻ trang này

Loading...