4 Replies Latest reply: Mar 11, 2013 1:15 AM by 993317 RSS

    Abstract Controller and Abstract View

    993317
      Hi, I am trying to create an Abstract Controller/View which is a Container having some Controls (Sort of a Template Container with Controls). Here is the code:
      package mvc;
      
      import javafx.fxml.FXML;
      import javafx.fxml.Initializable;
      import javafx.scene.control.TextField;
      
      public abstract class AbstractController implements Initializable {
      
          @FXML
          protected TextField nameField;
          @FXML
          protected TextField valueField;
          protected Model model;
      
          public AbstractController(Model model) {
              this.model = model;
          }
      }
      package mvc;
      
      import java.io.IOException;
      import javafx.fxml.FXMLLoader;
      import javafx.scene.layout.VBox;
      
      public class AbstractView {
      
          protected VBox template;
      
          public AbstractView(AbstractController controller) {
      
              FXMLLoader loader = new FXMLLoader(getClass().getResource("View.fxml"));
              loader.setController(controller);
              try {
                  loader.load();
              } catch (IOException ex) {
                  ex.printStackTrace();
              }
      
              template = loader.getRoot();
          }
      }
      <?xml version="1.0" encoding="UTF-8"?>
      
      <?import java.lang.*?>
      <?import java.util.*?>
      <?import javafx.scene.*?>
      <?import javafx.scene.control.*?>
      <?import javafx.scene.layout.*?>
      
      <VBox prefHeight="102.0" prefWidth="352.0" xmlns:fx="http://javafx.com/fxml">
        <children>
          <HBox alignment="CENTER" prefHeight="53.0" prefWidth="352.0">
            <children>
              <Label id="Name" text="Name" />
              <TextField fx:id="nameField" prefWidth="200.0" />
            </children>
          </HBox>
          <HBox alignment="CENTER" prefHeight="47.0" prefWidth="352.0">
            <children>
              <Label text="Value" />
              <TextField fx:id="valueField" prefWidth="200.0" />
            </children>
          </HBox>
        </children>
      </VBox>
      <?xml version="1.0" encoding="UTF-8"?>
      
      <?import java.lang.*?>
      <?import java.util.*?>
      <?import javafx.scene.*?>
      <?import javafx.scene.control.*?>
      <?import javafx.scene.layout.*?>
      
      <HBox alignment="CENTER" prefHeight="38.0" prefWidth="269.0" xmlns:fx="http://javafx.com/fxml">
        <children>
          <Label text="Title" />
          <TextField fx:id="titleField" prefWidth="200.0" />
        </children>
      </HBox>
      package mvc;
      
      import java.net.URL;
      import java.util.ResourceBundle;
      import javafx.fxml.FXML;
      import javafx.scene.control.TextField;
      
      public class Controller extends AbstractController {
      
          @FXML
          private TextField titleField;
      
          public Controller(Model model) {
              super(model);
          }
      
          @Override
          public void initialize(URL location, ResourceBundle resources) {
              nameField.setText(model.nameProperty().get());
              model.nameProperty().bind(nameField.textProperty());
      
              valueField.setText(model.valueProperty().get());
              model.valueProperty().bind(valueField.textProperty());
      
              titleField.setText(model.titleProperty().get());           //  Getting a NPE here.
              model.titleProperty().bind(titleField.textProperty());   //
          }
      }
      package mvc;
      
      import java.io.IOException;
      import javafx.fxml.FXMLLoader;
      import javafx.scene.layout.HBox;
      import javafx.scene.layout.Pane;
      
      public class View extends AbstractView {
      
          private HBox titleField;
      
          public View(AbstractController controller) {
              super(controller);
      
              FXMLLoader loader = new FXMLLoader(getClass().getResource("title.fxml"));
              loader.setController(controller);
              try {
                  loader.load();
              } catch (IOException ex) {
                  ex.printStackTrace();
              }
              titleField = loader.getRoot();
          }
      
          public Pane getpanel() {
              template.getChildren().add(titleField);
              return template;
          }
      }
      package mvc;
      
      import javafx.beans.property.SimpleStringProperty;
      import javafx.beans.property.StringProperty;
      
      public class Model {
      
          private StringProperty name;
          private StringProperty value;
          private StringProperty title;
      
          public Model(String name, String value) {
              this.name = new SimpleStringProperty(name);
              this.value = new SimpleStringProperty(value);
          }
      
          public Model(String name, String value, String title) {
              this(name, value);
              this.title = new SimpleStringProperty(title);
          }
      
          public StringProperty nameProperty() {
              return name;
          }
      
          public StringProperty valueProperty() {
              return value;
          }
      
          public StringProperty titleProperty() {
              return title;
          }
      }
      I am getting NPE in Controller.initialize method in the line titleField.setText(..). But if i comment out that line( and next line), I am able to launch the application but with empty value for titleField.
      Can someone please tell me where i am going wrong or if there is a flaw in the design.
        • 1. Re: Abstract Controller and Abstract View
          993317
          This is how i am starting the application:
          @Override
              public void start(Stage primaryStage) {
          
                  Model model = new Model("me", "hi", "title");
                  Controller c = new Controller(model);
                  View v = new View(c);
          
                  Scene scene = new Scene(v.getpanel(), 800, 600);
          
                  primaryStage.setTitle("Hello World!");
                  primaryStage.setScene(scene);
                  primaryStage.show();
              }
          This is the Exception:

          java.lang.NullPointerException
          file:/D:/NetBeansProjects/MVC/dist/MVC.jar!/mvc/View.fxml
          at mvc.Controller.initialize(Controller.java:25)
          at javafx.fxml.FXMLLoader.load(Unknown Source)
          at javafx.fxml.FXMLLoader.load(Unknown Source)
          at mvc.AbstractView.<init>(AbstractView.java:16)
          at mvc.View.<init>(View.java:13)
          at mvc.MVC.start(MVC.java:14)
          at com.sun.javafx.application.LauncherImpl$5.run(Unknown Source)
          at com.sun.javafx.application.PlatformImpl$5.run(Unknown Source)
          at com.sun.javafx.application.PlatformImpl$4.run(Unknown Source)
          at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
          at com.sun.glass.ui.win.WinApplication.access$100(Unknown Source)
          at com.sun.glass.ui.win.WinApplication$3$1.run(Unknown Source)
          at java.lang.Thread.run(Thread.java:662)

          Exception in Application start method
          java.lang.reflect.InvocationTargetException
               at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
               at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
               at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
               at java.lang.reflect.Method.invoke(Method.java:597)
               at com.javafx.main.Main.launchApp(Main.java:642)
               at com.javafx.main.Main.main(Main.java:805)
          Caused by: java.lang.RuntimeException: Exception in Application start method
               at com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source)
               at com.sun.javafx.application.LauncherImpl.access$000(Unknown Source)
               at com.sun.javafx.application.LauncherImpl$1.run(Unknown Source)
               at java.lang.Thread.run(Thread.java:662)
          Caused by: java.lang.NullPointerException
               at mvc.Controller.initialize(Controller.java:25)
               at javafx.fxml.FXMLLoader.load(Unknown Source)
               at javafx.fxml.FXMLLoader.load(Unknown Source)
               at mvc.AbstractView.<init>(AbstractView.java:16)
               at mvc.View.<init>(View.java:13)
               at mvc.MVC.start(MVC.java:14)
               at com.sun.javafx.application.LauncherImpl$5.run(Unknown Source)
               at com.sun.javafx.application.PlatformImpl$5.run(Unknown Source)
               at com.sun.javafx.application.PlatformImpl$4.run(Unknown Source)
               at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
               at com.sun.glass.ui.win.WinApplication.access$100(Unknown Source)
               at com.sun.glass.ui.win.WinApplication$3$1.run(Unknown Source)
               ... 1 more
          Java Result: 1
          jfxsa-run:
          BUILD SUCCESSFUL (total time: 7 seconds)
          • 2. Re: Abstract Controller and Abstract View
            993317
            some help here please
            • 3. Re: Abstract Controller and Abstract View
              lgringo
              Hi, you can't use @FXML annotations in super classes (as you want to do): See this demand : http://javafx-jira.kenai.com/browse/RT-16722
              • 4. Re: Abstract Controller and Abstract View
                993317
                Thanks. I hope this feature is provided in future.