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

Java F X With Multiple F X M L Files

Discussion in 'Java Update' started by Joe, 26/8/19.

  1. Joe

    Joe Thành viên VIP

    Hi everyone

    Today I show you how to build a JavaFX application with Multiple FXML. As you know, JFX-App can be either a monolith or a Model-View-Control (MVC). A monolithic Application is usually a straight-forward development and does have some advantages, too. However, the greatest disadvantage is the enhancement/correction problems. It usually requires a "redesign" and "recompile" of the whole app.

    MVC development is on the other hand flexible, but it could be confusing, too. Too many (little) modules could mess an overview of the whole. Especially when your app requires different models which are controlled and viewed by different FXML files. I show you today how to create an app with 4 different FXMLs and Controllers.

    [​IMG]

    There are different ways to implement a multiple MVC-JFX application. The simplest way is to implement a principal controller which controls the main FXML view and the other controllers. Each Sub-Controller controls its own FXML View Model which is independent from each other. This way allows you to modify or to enhance a view model without having to redesign or to recompile the other modules. I show you a ZOO-MVC which consists of a main controller and 3 sub-controllers with their own FXML-View-Model.

    The multiple FXML mechanism works as following:

    - Main View (fxml/controller) instantiates all other Sub-ViewModels
    - Each Sub-ViewModel works independently from other Sub-ViewModel, but it can initiate or set up some parts of other Sub-ViewModels.

    The JFX Zoo.java app starts with its ZooController.java which presents the view zoo.fxml model of 3 Tabs: Animals, About Animal and Video. Each Tab represents a new ViewModel and Controller (animal.fxml/AnimalController.java, info.fxml/InfoController.java, video.xml/VideoController.java). The starting Tab is the Animals Tab (with 2 columns: animal names and image.) If an animal is selected (e.g. Mustang) ZooController starts to initiate the 2 other Tabs (About Animal and Video) according to the specified animal.

    The ZooController
    PHP:
    public class ZooController {
     
        @
    FXML private InfoController infoController;        // 1st. controller
        
    @FXML private VideoController videoController;      // 2nd. controller
        
    @FXML private AnimalController animalController;    // 3rd. controller
     
        
    @FXML private void initialize() {
            
    animalController.injectAnimalController(this);
        }
        
    /*
        Main controller controls the 3 other controllers.
        */
        
    @FXML
        
    private void mouseClicked(MouseEvent e) {
            
    animalController.setEvent(e);
        }
        public 
    void setInfo(String url ) {
            
    infoController.setInfo(url);
        }
        public 
    void setVideo(String url) {
            
    videoController.setVideo(url);
        }
    }
    and its View FXML model
    PHP:
    <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
                
    minWidth="-Infinity" prefHeight="470.0" prefWidth="800.0"
                
    xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
                
    fx:controller="ZooController">
       <
    children>
          <
    TabPane layoutX="127.0" layoutY="90.0"
                   
    tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0"
                   
    AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
                   
    AnchorPane.topAnchor="0.0" onMouseClicked="#mouseClicked">
            <
    tabs>
              <
    Tab text="Animals">
                   <
    content>
                      <
    fx:include fx:id="animal" source="Animal.fxml" />
                   </
    content>
              </
    Tab>
              <
    Tab text="About Animal">
                   <
    content>
                      <
    fx:include fx:id="info" source="Info.fxml" />
                   </
    content>
              </
    Tab>
              <
    Tab text="Video">
                   <
    content>
                      <
    fx:include fx:id="video" source="Video.fxml" />
                   </
    content>
              </
    Tab>
            </
    tabs>
          </
    TabPane>
       </
    children>
    </
    AnchorPane>
    The AnimalController manages a list (zoolist.txt) of registered animals (name, link to Wikipedia, link to an image and link to the according Youtube or link to your own clip) with two possibilities:
    - ADD: add a new animal to the list. Here you can see how a multiple TextField-Dialog works.
    - DEL: delete an animal from the list.
    PHP:
    public class AnimalController {
     
      @
    FXML private Pane infoPane;
      @
    FXML private TextArea infoText;
      @
    FXML private ListView<StringanimalList;
     
      public 
    void injectAnimalController(ZooController zooController){
        
    this.zooController zooController;
      }
     
      @
    FXML
      
    public void initialize() {
        
    urlList = new ArrayList<String>();
        
    picList = new ArrayList<String>();
        
    videoList = new ArrayList<String>();
        
    animals FXCollections.observableArrayList();
        try {
          
    byte[] cont Files.readAllBytes((new File("ZooList.txt")).toPath());
          
    String[] = (new String(cont)).split(sp);
          for (
    int n 0s.length; ++n) {
            
    String[] s[n].split("!");
            
    animals.add(e[0]);
            
    urlList.add(ne[1]);
            
    picList.add(ne[2]);
            
    videoList.add(ne[3]);
          }
        } catch (
    Exception ex) {
          ...
        }
        
    animalList.setItems(animals);
      }
     
      public 
    void setEvent(MouseEvent e) {
        
    //System.out.println("X="+e.getX()+", Y="+e.getY());
      
    }
     
      @
    FXML
      
    private void addAnimal(ActionEvent e) {
        
    lst getList();
        if (
    lst != null && !lst.get(0).isEmpty()) {
          
    animals.add(lst.get(0));
          
    picList.add(lst.get(1));
          
    urlList.add(lst.get(2));
          
    videoList.add(lst.get(3));
          try (
    FileOutputStream fout = new FileOutputStream("ZooList.txt"true)) {
            
    fout.write((lst.get(0)+"!"+lst.get(1)+"!"+lst.get(2)+"!"+lst.get(3)+sp).getBytes());
            
    fout.flush();
            
    fout.close();
          } catch (
    Exception ex) {}
        }
      }
     
      @
    FXML
      
    private void delAnimal(ActionEvent e) {
        
    TextInputDialog dialog = new TextInputDialog("AnimalName");
        
    dialog.setTitle("Delete AnimalName");
        
    dialog.setHeaderText("Remove an AnimalName from ZOO");
        
    dialog.setContentText("AnimalName:");
        
    // Traditional way to get the response value.
        
    Optional<Stringresult dialog.showAndWait();
        if (
    result.isPresent()){
          ...
        }
      }
     
      @
    FXML
      
    private void onMouseClicked(MouseEvent e) {
        
    infoPane.getChildren().clear();
        
    int idx animalList.getSelectionModel().getSelectedIndex();
        if (
    idx >= 0) {
          
    // synchronize Tab "About Animal"
          
    zooController.setInfo(urlList.get(idx));
          
    // synchronize Tab "Video"
          
    zooController.setVideo(videoList.get(idx));
          
    // Image Tab
          
    try {
            
    ImageView imgView = new ImageView(new Image(picList.get(idx)));
            
    infoPane.getChildren().add(imgView);
            
    imgView.fitWidthProperty().bind(infoPane.widthProperty());
            
    imgView.fitHeightProperty().bind(infoPane.heightProperty());
          } catch (
    Exception ex) {
            
    ex.printStackTrace();
          }
        }
      }
      private 
    ArrayList<StringgetList() {
        
    ArrayList<String> list = new ArrayList<String>();
        
    Dialog<List<String>> dialog = new Dialog<>();
        
    dialog.setTitle("Add New Animal");
        
    dialog.setHeaderText("Links to Image, Wiki and Youtube");
     
        
    // Set the button types.
        
    ButtonType aBut = new ButtonType("ADD"ButtonData.OK_DONE);
        
    dialog.getDialogPane().getButtonTypes().addAll(aButButtonType.CANCEL);
     
        
    // Create the animalName and password labels and fields.
        
    GridPane grid = new GridPane();
        
    grid.setHgap(10);
        
    grid.setVgap(10);
        
    grid.setPadding(new Insets(201501010));
     
        
    TextField animalName = new TextField();
        
    animalName.setPromptText("AnimalName");
        
    TextField img = new TextField();
        
    img.setPromptText("ImageLink");
        
    TextField wiki = new TextField();
        
    wiki.setPromptText("WikiLink");
        
    TextField youtube = new TextField();
        
    youtube.setPromptText("YoutubeLink");
     
        
    grid.add(new Label("AnimalName:"), 00);
        
    grid.add(animalName10);
        
    grid.add(new Label("WikiLink:"), 01);
        
    grid.add(img11);
        
    grid.add(new Label("ImageLink:"), 02);
        
    grid.add(wiki12);
        
    grid.add(new Label("YoutubeLink:"), 03);
        
    grid.add(youtube13);
        ...
        return list;
      }
      ...
    }
    AnimalController manages a list of animals. Each entry consists of a Name, a Link to Wikipedia, a Link to a Web-image and a Link to a video clip (e.g. Youtube). Any modification (add/del) will be saved when Zoo-App terminates (see method panicShutdown). And the ViewModel
    PHP:
    <SplitPane fx:id="animal" xmlns="http://javafx.com/javafx/8"
        
    xmlns:fx="http://javafx.com/fxml/1" fx:controller="AnimalController"
        
    dividerPositions="0.233" prefHeight="180.0" prefWidth="200.0"
        
    AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
        
    AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <
    items
          <
    VBox spacing="5" alignment="bottom_center" >
             <
    padding><Insets  right="5" left="5" bottom="5" /></padding>
             <
    children>
                <
    ListView fx:id="animalList" onMouseClicked="#onMouseClicked" />
                <
    HBox spacing="5" alignment="bottom_center" >
                  <
    Button fx:id="ADD" onAction="#addAnimal" text="ADD"
                      
    prefHeight="20.0" prefWidth="80.0" />
                  <
    Button fx:id="DEL" onAction="#delAnimal" text="DEL"
                      
    prefHeight="20.0" prefWidth="80.0" />
                  </
    HBox>
               </
    children>
            </
    VBox>
           <
    Pane fx:id="infoPane" minHeight="0.0" minWidth="0.0"
                
    prefHeight="428.0" prefWidth="511.0" >
           </
    Pane>                         
        </
    items>
    </
    SplitPane>
    The other Tabs are;
    PHP:
    public class InfoController {
        @
    FXML private Pane infoPane;
     
        private 
    WebEngine wNgine;
     
        @
    FXML public void initialize() {
            
    WebView vView = new WebView();
            
    wNgine wView.getEngine();
            
    infoPane.getChildren().add(wView);
        }
        public 
    void setInfo(String url) {
            
    wNgine.load(url);
        }
    }
    PHP:
    <Pane fx:id="infoPane"
          
    xmlns="http://javafx.com/javafx/8"
          
    xmlns:fx="http://javafx.com/fxml/1"
          
    fx:controller="InfoController"
    />
    PHP:
    public class VideoController {
        @
    FXML private Pane videoPane;
     
        private 
    WebEngine vNgine;
     
        @
    FXML public void initialize() {
            
    WebView vView = new WebView();
            
    vNgine vView.getEngine();
            
    videoPane.getChildren().add(vView);
        }
     
        public 
    void setVideo(String url) {
            
    vNgine.load(url);
        }
    }
    PHP:
    <Pane fx:id="videoPane"
          
    xmlns="http://javafx.com/javafx/8"
          
    xmlns:fx="http://javafx.com/fxml/1"
          
    fx:controller="VideoController"
    />
    The complete sources can be downloaded hereunder.
     

    Attached Files:

    • cdj.zip
      File size:
      5.8 KB
      Views:
      0
    Last edited: 28/8/19
    Thanhpv likes this.

Chia sẻ trang này

Loading...