fx:id=grid остается нулевым в контроллере

сетка остается нулевой, когда пользователь нажимает кнопку, которая вызывает «pressLookUp». Пользователь должен перейти от старого этапа к новому в файле fxml. И до того, как будет показано новое окно, я хочу добавить значения в дочерние элементы сетки из базы данных, используя grid.add(node, colIndex, rowIndex)

Контроллер:

package login;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import userGroups.User;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class studentOptionsController{
@FXML
private GridPane grid;//gridpane from ClassesToAdd

public void pressLookUp(ActionEvent event) throws IOException{
    Parent userOption = FXMLLoader.load(getClass().getResource("ClassesToAdd.fxml"));
    Scene classesToAddScene = new Scene(userOption);
    Stage app_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
    app_stage.setScene(classesToAddScene);
    app_stage.show();

    Connection c = null;
    Statement stmt = null;
    try{
        c = DriverManager.getConnection("jdbc:sqlite:users.db");
        c.setAutoCommit(false);

        System.out.println("Opened database successfully");
        stmt = c.createStatement();

        ResultSet rs = stmt.executeQuery("SELECT * FROM Classes WHERE IDCLASSES= " + "5;");

        int currentIndex = 0;
        int currentRow = 0;
        //assusming all columns are NOT NULL
        while(rs.next()){
            Label currentLabel = new Label();
            currentLabel.setText(rs.getString("CLASSNAME"));
            System.out.println(currentLabel.getText());
            grid.add(currentLabel, 5, 0 );
            /*if (rs.getString("SUSERNAME") != null && rs.getString("STUDENTPASS") != null){
                String  username = rs.getString("SUSERNAME");
                System.out.println( "SUSERNAME = " + username );
                String password = rs.getString("STUDENTPASS");
                System.out.println("STUDENTPASS = " + password);
            }*/
        }
        rs.close();
        stmt.close();
        c.close();
    } catch ( Exception e ){
        System.err.println( e.getClass().getName() + ": " + e.getMessage() );
        //System.exit(0);
    }
    System.out.println("Operation done successfully");
}
}

FXML:

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>

<GridPane fx:id="grid" prefHeight="400.0" prefWidth="850" 
xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" 
fx:controller="login.studentOptionsController">
  <columnConstraints>
      <ColumnConstraints percentWidth="11" />
      <ColumnConstraints percentWidth="11" />
      <ColumnConstraints percentWidth="11" />
      <ColumnConstraints percentWidth="11" />
      <ColumnConstraints percentWidth="11" />
      <ColumnConstraints percentWidth="11" />
      <ColumnConstraints percentWidth="11" />
      <ColumnConstraints percentWidth="11" />
       <ColumnConstraints percentWidth="12" /> <!-- This column for 'Add 
 Class' buttons ?-->
   </columnConstraints>
   <rowConstraints>
      <RowConstraints />
   </rowConstraints>
   <children>
  <Label maxHeight="Infinity" maxWidth="Infinity" style=" -fx-border-color:gray; " text="Class Name" GridPane.columnIndex="0" GridPane.rowIndex="0" />
  <Label maxHeight="Infinity" maxWidth="Infinity" style=" -fx-border-color:gray; " text="Size of Class" GridPane.columnIndex="1" GridPane.rowIndex="0" />
  <Label maxHeight="Infinity" maxWidth="Infinity" style=" -fx-border-color:gray; " text="Spots Taken" GridPane.columnIndex="2" GridPane.rowIndex="0" />
  <Label maxHeight="Infinity" maxWidth="Infinity" style=" -fx-border-color:gray; " text="Instructor" GridPane.columnIndex="3" GridPane.rowIndex="0" />
  <Label maxHeight="Infinity" maxWidth="Infinity" style=" -fx-border-color:gray; " text="CRN" GridPane.columnIndex="4" GridPane.rowIndex="0" />
  <Label maxHeight="Infinity" maxWidth="Infinity" style=" -fx-border-color:gray; " text="Days" GridPane.columnIndex="5" GridPane.rowIndex="0" />
  <Label maxHeight="Infinity" maxWidth="Infinity" style=" -fx-border-color:gray; " text="Time" GridPane.columnIndex="6" GridPane.rowIndex="0" />
  <Label maxHeight="Infinity" maxWidth="Infinity" style=" -fx-border-color:gray; " text="Subject" GridPane.columnIndex="7" GridPane.rowIndex="0" />
  <Button maxHeight="Infinity" maxWidth="Infinity" mnemonicParsing="false" onAction="#pressBack" style=" -fx-background-color:red; -fx-border-color:black" text="Back..." GridPane.columnIndex="8" GridPane.rowIndex="0" />
   </children>
</GridPane>

Вывод в системе:

Opened database successfully
java.lang.NullPointerException: null
Operation done successfully

person Michael Lin    schedule 27.03.2018    source источник
comment
В FXML нет кнопки (или любого другого элемента управления), связанного с pressLookUp(). Как это вообще называется?   -  person James_D    schedule 27.03.2018
comment
Это кнопка из предыдущего этапа из отдельного FXML. Сама смена сцены работает   -  person Michael Lin    schedule 27.03.2018
comment
Хорошо, но есть ли в этом файле FXML элемент с fx:id=grid? В противном случае grid будет инициализирован только в контроллере, созданном при загрузке опубликованного вами файла FXML; он не будет инициализирован в контроллере, созданном при загрузке другого файла FXML. (И, конечно же, pressLookUp() вызывается на контроллере, который создается при загрузке другого файла FXML.)   -  person James_D    schedule 27.03.2018
comment
По сути, очень плохая идея использовать один и тот же класс для контроллеров для двух разных файлов FXML; слишком сложно отслеживать, какие поля в каких контроллерах инициализированы и какие поля все еще пусты. Я бы рекомендовал использовать разные классы контроллеров для каждого файла FXML. В любом случае вам нужно вызвать метод на правильном контроллере, используя методы, подобные описанным в stackoverflow.com/q/14187963.   -  person James_D    schedule 27.03.2018
comment
Gridpane в файле fxml имеет fx:id=grid. Метод pressLookUp должен находиться в том же файле, поскольку предполагается, что он добавляет элементы управления на следующем этапе. Если вы поместите его в другой контроллер, я не понимаю, как это будет работать.   -  person Michael Lin    schedule 27.03.2018
comment
Предыдущий fxml/stage ничего не имеет с fx:id=grid. Мне просто нужно знать, как сделать переменную не нулевой. И когда я отлаживаю строки с точками останова, при этом он всегда показывает сетку как нулевую по какой-то причине.   -  person Michael Lin    schedule 27.03.2018
comment
Но если они находятся в разных файлах FXML, то они уже находятся в разных контроллерах. Просто сделать оба контроллера одним классом совсем не помогает; это только еще больше сбивает с толку.   -  person James_D    schedule 27.03.2018
comment
Я не понимаю? Единственным подходящим методом, который теоретически мог бы находиться в отдельном классе контроллера, была бы функция onAction=#pressBack. Я не знаю, как вы можете загрузить из базы данных со 2-го контроллера   -  person Michael Lin    schedule 27.03.2018
comment
pressLookUp предназначен только для добавления элементов в существующую панель сетки на отдельном этапе, указанном в файле fxml.   -  person Michael Lin    schedule 27.03.2018
comment
У вас уже есть два контроллера (потому что вы дважды вызываете FXMLLoader.load(...), что вы должны делать, потому что у вас есть два файла FXML). Вы должны решить проблему связи между ними, независимо от того, делаете ли вы оба этих контроллера одним и тем же классом или разными классами. Решить эту проблему будет проще, если сделать их разными классами. Я не могу показать вам, как это сделать, потому что вы не опубликовали соответствующий код. Я рекомендую вам создать и опубликовать минимально воспроизводимый пример (или найти похожие вопросы на этом сайте; их много) .   -  person James_D    schedule 27.03.2018
comment
Отредактировал контроллер, чтобы включить весь файл Java. Когда я попытался прокомментировать другой файл FXMLLoader.load, это все равно не решило проблему.   -  person Michael Lin    schedule 27.03.2018


Ответы (1)


Не знаю, почему это работает, но это работает.

public void pressLookUp(ActionEvent event) throws IOException{
    FXMLLoader loader = new FXMLLoader(getClass().getResource("ClassesToAdd.fxml"));
    Parent userOption = loader.load();
    grid = loader.getRoot();
    Scene classesToAddScene = new Scene(userOption);
    Stage app_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
    app_stage.setScene(classesToAddScene);
    app_stage.show();
    Connection c = null;
    Statement stmt = null;
    try{
        c = DriverManager.getConnection("jdbc:sqlite:users.db");
        c.setAutoCommit(false);

        System.out.println("Opened database successfully");
        stmt = c.createStatement();

        ResultSet rs = stmt.executeQuery("SELECT * FROM Classes WHERE IDCLASSES= " + "5;");

        int currentIndex = 0;
        int currentRow = 0;
        //assusming all columns are NOT NULL
        while(rs.next()){
            Label currentLabel = new Label();
            currentLabel.setText(rs.getString("CLASSNAME"));
            System.out.println(currentLabel.getText());
            grid.add(currentLabel, 0, 1 );
        }
        loader.setRoot(grid);
        rs.close();
        stmt.close();
        c.close();
    } catch ( Exception e ){
        System.err.println( e.getClass().getName() + ": " + e.getMessage() );
        System.exit(0);
    }
    System.out.println("Operation done successfully");
}
person Michael Lin    schedule 28.03.2018