MusH
MusH

Reputation: 85

Buttons Stop working when I add TableView Functionality in the initialize() method

My buttons were working well before I added the table (TableView) functionality to my code, but now an error occurs once I click on the same buttons. The error disappears and the buttons works if I comment out this lines of code in RoomsController:

intRoomIDColVR.setCellValueFactory(new PropertyValueFactory<>("roomID"));
vachRoomTypeIDColVR.setCellValueFactory(new PropertyValueFactory<>("roomTypeID"));
roomTableViewVR.setItems(olRoomData);

The FXML file:

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

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.codetech.hotelmis.controller.RoomsController">
    <children>
      <BorderPane prefHeight="338.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <center>
          <Accordion BorderPane.alignment="CENTER">
            <panes>
              <TitledPane fx:id="accVacant" animated="false" text="Vacant Rooms">
                <content>
                  <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                    <children>
                              <BorderPane prefHeight="324.0" prefWidth="598.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                                 <center>
                            <TableView fx:id="roomTableViewVR" BorderPane.alignment="CENTER">
                              <columns>
                                <TableColumn fx:id="intRoomIDColVR" prefWidth="75.0" text="Room ID" />
                                <TableColumn fx:id="vachRoomTypeIDColVR" prefWidth="115.00000762939453" text="Room Type" />
                                          <TableColumn fx:id="reservedColVR" prefWidth="94.0" text="Reserved?" />
                                          <TableColumn fx:id="resCustomerColVR" prefWidth="95.0" text="Customer " />
                              </columns>
                            </TableView>
                                 </center>
                                 <top>
                                    <HBox>
                                       <children>
                                          <Button fx:id="btnCheckInPopUp" mnemonicParsing="false" text="Check In" BorderPane.alignment="CENTER" />
                                       </children>
                                    </HBox>
                                 </top>
                              </BorderPane>
                    </children>
                  </AnchorPane>
                </content>
              </TitledPane>
              <TitledPane fx:id="accOccupied" animated="false" text="Occupied Rooms">
                <content>
                  <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                    <children>
                              <BorderPane prefHeight="324.0" prefWidth="598.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                                 <top>
                                    <HBox>
                                       <children>
                                          <Button fx:id="btnTabCheckOut" mnemonicParsing="false" text="Check Out" BorderPane.alignment="CENTER" />
                                       </children>
                                    </HBox>
                                 </top>
                                 <center>
                                    <TableView BorderPane.alignment="CENTER">
                                       <columns>
                                          <TableColumn fx:id="intRoomIDColOR" prefWidth="75.0" text="Room ID" />
                                          <TableColumn fx:id="vachRoomTypeIDColOR" prefWidth="115.00000762939453" text="Room Type" />
                                          <TableColumn fx:id="occupantColOR" prefWidth="83.0" text="Occupant" />
                                          <TableColumn fx:id="checkInDateColOR" prefWidth="121.0" text="Check In Date" />
                                          <TableColumn fx:id="checkOutDateColOR" prefWidth="181.99996948242188" text="Expected Check Out Date" />
                                       </columns>
                                    </TableView>
                                 </center>
                              </BorderPane>
                    </children>
                  </AnchorPane>
                </content>
              </TitledPane>
            </panes>
          </Accordion>
        </center>
        <top>
          <HBox prefHeight="24.0" prefWidth="600.0" BorderPane.alignment="CENTER">
            <children>
              <Button fx:id="btnNewRoom" mnemonicParsing="false" text="New Room" />
              <Button fx:id="btnEditRoom" mnemonicParsing="false" text="Edit Room" />
                  <Button fx:id="btnNewRoomType" mnemonicParsing="false" text="New Room Type" />
                  <Button fx:id="btnEditRoomType" mnemonicParsing="false" text="Edit Room Type" />
                  <Button fx:id="btnGuestLog" mnemonicParsing="false" text="Guest Log" />
            </children>
          </HBox>
        </top>
      </BorderPane>
    </children>
</AnchorPane>

The Controller Class:

    public class RoomsController implements Initializable {
    @FXML
    private TableView<RoomData> roomTableViewVR;
    @FXML
    private TableColumn<RoomData, Integer> intRoomIDColVR;
    @FXML
    private Button btnCheckInPopUp;
    @FXML
    private TableColumn<RoomData, String> vachRoomTypeIDColVR;

    //Declare ObservableList
    private ObservableList<RoomData> olRoomData;

    private ActionEvent event;
    private static Connection con;
    private static ResultSet rs;
    private static java.sql.Statement stmt;
    private static String sql;
    JavaToMySQL javaToMySQL = new JavaToMySQL();

    public RoomsController() {
        try {
            con = DatabaseConnection.getConnected();
            stmt = con.createStatement();
            olRoomData = FXCollections.observableArrayList();
            rs = con.createStatement().executeQuery("SELECT * FROM h_r_rooms");
            while (rs.next()){
                olRoomData.add(new RoomData(rs.getInt("intRoomID"),rs.getString("vachRoomTypeID")));
            }
        } catch (SQLException e) {
            e.printStackTrace();
            System.out.println("Error on Building Data");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        listeners();

        intRoomIDColVR.setCellValueFactory(new PropertyValueFactory<>("roomID"));
        vachRoomTypeIDColVR.setCellValueFactory(new PropertyValueFactory<>("roomTypeID"));
        roomTableViewVR.setItems(olRoomData);
    }

    void listeners(){
        btnCheckInPopUp.setOnAction((event -> {
            System.out.println("I'm supposed to pop out a Check In window when you click me!");

            Stage stage;
            if (event.getSource()== btnCheckInPopUp){
                stage = new Stage();
                try {
                    Parent root = FXMLLoader.load(getClass().getResource("../view/popups/check_in.fxml"));
                    System.out.println("I work!");
                    stage.setScene(new Scene(root));
                    stage.setTitle("Check Customer In");
                    stage.initModality(Modality.APPLICATION_MODAL);
                    stage.initOwner(btnCheckInPopUp.getScene().getWindow());
                    stage.showAndWait();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }));
    }
}

When I click on the Check In(btnCheckInPopUp) the following error appears:

The Connection is open!
javafx.fxml.LoadException: 
/home/mush/Programming/Dev/InteliJProjects/Hotel_MIS/out/production/Hotel_MIS/com/codetech/hotelmis/view/popups/check_in.fxml

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2605)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2583)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2445)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3218)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3179)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3152)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3128)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3108)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3101)
    at com.codetech.hotelmis.controller.RoomsController.lambda$listeners$0(RoomsController.java:87)
    at com.codetech.hotelmis.controller.RoomsController$$Lambda$104/1394020985.handle(Unknown Source)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Node.fireEvent(Node.java:8390)
    at javafx.scene.control.Button.fire(Button.java:185)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3758)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3486)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2495)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:350)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$350(GlassViewEventHandler.java:385)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$252/507580015.get(Unknown Source)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:404)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:384)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:927)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$null$48(GtkApplication.java:139)
    at com.sun.glass.ui.gtk.GtkApplication$$Lambda$43/1166661505.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
    at com.codetech.hotelmis.controller.RoomsController.initialize(RoomsController.java:74)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2552)
    ... 70 more

I've really tried to figure out why but to no avail. I'd really appreciate the help and I will provide any more details concerning the code required to solve the issue.

The problem here seems quite similar to mine.

Upvotes: 0

Views: 72

Answers (1)

James_D
James_D

Reputation: 209225

It appears you are using the same controller class for two different FXML files. Don't do this: use a different controller for each FXML.

When the FXMLLoader's load() method is called, it does the following (somewhat simplified description):

  1. Reads the FXML file
  2. If the FXML file specifies a controller class, it creates a new instance of the controller class by calling its no-argument constructor
  3. Creates an object hierarchy based on the FXML elements
  4. Sets event handlers on the elements, mapping to the controller class instance created in step 1
  5. For elements with an fx:id attribute, it injects the corresponding objects into any matching @FXML-annotated references in the controller instance
  6. Calls initialize() on the controller instance, if such a method exists.
  7. Returns the object corresponding to the root element of the FXML file.

In your case, you have two FXML files specifying the same controller class. When the "main" FXML file is loaded, the process above happens. A first instance of RoomsController is created, its @FXML-annotated fields matching fx:ids are injected (including intRoomIDColVR and others), event handlers are registered, and the initialize() method is called. All is fine at this point.

When the btnCheckInPopup button is pressed, its onAction handler is invoked. This causes check_in.fxml to be loaded. Since this specifies the same controller class, a second instance of that class is created. @FXML-annotated fields corresponding to elements of check_in.fxml with matching fx:ids are injected. However, note that, since check_in.fxml doesn't define any element with fx_id="intRoomIDColVR", intRoomIDColVR is not initialized for this second controller instance. The initialize() method is then invoked on this second controller instance, and since intRoomIDColVR is not initialized, this causes a NullPointerException at the line

intRoomIDColVR.setCellValueFactory(new PropertyValueFactory<>("roomID"));

This is a pretty good example of exactly why each FXML should have its own controller class. It gets very hard to keep track of which fields are initialized and which are not at any given time, and for any specific instance of the class, if you "share" controller classes like this.

Upvotes: 1

Related Questions