2015-08-28 4 views
0

У меня действительно простой класс, который принимает список заданий и пытается заполнить TableView ими. У меня это работает без использования FXML, но теперь я пытаюсь использовать новые методы. У меня проблема:JavaFX TableView с SceneBuilder

tView.getItems().addAll(jobList); 

возвращает нулевой указатель, однако, если я создаю новый TableView, данных в таблице вообще нет.

Я считаю, что, когда я ошибаюсь, использование TableView, которое построено в SceneBuilderand, неправильно инициализирует его, однако я смущен тем, как я это сделаю. Вот мой класс метода InterFace;

public class InterfaceMethods { 

    @FXML TableView<Job> tView; 

    @SuppressWarnings("unchecked") 
    public void populateTableView(Connection connection, Stage stage) throws Exception { 

     Parent root; 
     root = FXMLLoader.load(getClass().getResource("TableViewInterface.fxml")); 
     Scene scene = new Scene(root); 
     stage.setScene(scene); 

     JobDataAccessor jobAccessor = new JobDataAccessor(); 
     final String query = "SELECT * FROM progdb.adamJobs"; 
     List<Job> jobList = jobAccessor.getJobList(connection, query); 
     //System.out.println(query); 
     //System.out.println(connection); 
     tView.getItems().addAll(jobList); 
    } 
} 

Это мой класс MainApp;

public class MainApp extends Application { 

private CheckUserDetails checkDetails; 
private String pString, username = System.getProperty("user.name"); 
private InterfaceMethods iMethods; 
private Connection connection; 
@FXML private Button submitButton; 
@FXML private PasswordField passField; 
@FXML private Label warnLabel; 

@Override 
public void start(Stage stage) throws Exception { 
    Parent root = FXMLLoader.load(getClass().getResource("MainInterface.fxml")); 
    Scene scene = new Scene(root); 
    stage.setScene(scene); 
    stage.show(); 
} 

@FXML 
private void loginCheck() throws Exception { 
    checkDetails = new CheckUserDetails(); 
    pString = new String(); 
    pString = passField.getText(); 
    System.out.println(pString); 
    if (checkDetails.checkUserDetails(pString, username) != null) { 
     setConnection(checkDetails.connection); 
     handleTableView(); 
    } else { 
     warnLabel.setVisible(true); 
    } 
} 

@FXML 
public void handleTableView() throws Exception { 
    iMethods = new InterfaceMethods(); 

    Stage stage = (Stage) submitButton.getScene().getWindow(); 

    connection = getConnection(); 

    iMethods.populateTableView(connection, stage); 
} 

public static void main(String[] args) { 
    launch(args); 
} 

Наконец, вот один из двух моих файлов FXML, один с TableView внутри него;

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

<?import javafx.scene.control.*?> 
<?import java.lang.*?> 
<?import javafx.scene.layout.*?> 
<?import javafx.scene.layout.GridPane?> 

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.InterfaceMethods"> 
    <children> 
     <TableView fx:id="tView" layoutX="17.0" layoutY="19.0" prefHeight="347.0" prefWidth="570.0"> 
     <columns> 
      <TableColumn prefWidth="75.0" text="CaseNO." /> 
      <TableColumn prefWidth="75.0" text="Case Notes" /> 
      <TableColumn prefWidth="75.0" text="Date Created" /> 
      <TableColumn prefWidth="75.0" text="Deadline" /> 
      <TableColumn prefWidth="75.0" text="Priority" /> 
      <TableColumn prefWidth="75.0" text="Completed" /> 
     </columns> 
     <columnResizePolicy> 
      <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> 
     </columnResizePolicy> 
     </TableView> 
    </children> 
</AnchorPane> 

Метод getJobList (внутри другого класса);

public List<Job> getJobList(final Connection connection, final String query) throws SQLException { 
    try (Statement stmnt = connection.createStatement(); ResultSet rs = stmnt.executeQuery(query);) { 
     jobList = new ArrayList<>(); 
     System.out.println(connection); 
     System.out.println(query); 
     while (rs.next()) { 
      caseNumber = rs.getString("CaseNO"); 
      caseNotes = rs.getString("CaseNotes"); 
      dateCreated = rs.getString("DateCreated"); 
      deadlineDate = rs.getString("Deadline"); 
      prioritySetting = rs.getInt("Priority"); 
      completedSetting = rs.getString("Completed"); 
      job = new Job(caseNumber, caseNotes, dateCreated, deadlineDate, prioritySetting, completedSetting); 
      jobList.add(job); 
     } 
     return jobList; 
    } 
} 
+0

Файл fx: id TableView в файле FXML должен совпадать с именем в классе conrtoller, т. Е."Tableview". Не так ли, проверьте это? –

+0

Это точно то же самое. Я также обновлю вопрос с помощью своего класса контроллера. – jbanks

+0

расширить класс контроллера с помощью javafx.fxml.Initializableclass. – Hareesh

ответ

0

Вам необходимо определить контроллер для FXML.

Например ваша часть FXML является: -

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="288.0" prefWidth="293.0" xmlns:fx="http://javafx.com/fxml"> 
<children> 
    <TableView fx:id="tableView" layoutX="35.0" layoutY="28.0" prefHeight="200.0" prefWidth="227.0"> 
    <columns> 
     <!-- Columns for table view--> 
    </columns> 
    </TableView> 
</children> 
</AnchorPane> 

1) Создание контроллера для вашей страницы FXML, как: -

fx:controller="com.code.Controller" 

2) Теперь в вашем контроллере, вы можете do:

package com.code; 

    public class Controller implements Initializable { 

     @FXML private TableView<User> tableView; 
+0

Спасибо за комментарий Amit. Я проверил, и у моего FXML уже есть контроллер: 'fx: controller =" application.MainApp "'. Теперь в моем контроллере (MainApp) у меня есть: @FXML private TableView tableView; 'и затем попытаться вызвать метод. – jbanks

+0

@jbanks, но он говорит, что ваше имя класса conrtoller - это «InterfaceMethods» в вопросе. –

+0

@Uluk Biy Извиняется за мою ошибку, контроллер на самом деле InterfaceMethods (я пробовал другой контроллер, изменил его обратно на fx: controller = "application.InterfaceMethods" сейчас), я все еще получаю исключение из null-указателя, неутешительно. Не слишком уверен, где я ошибаюсь. – jbanks

0

Все аннотированные поля @FXML класса контроллера созданный FXMLLoader при загрузке файла fxml с fx:controller, равным этому классу контроллера, или классу, заданному fxmlLoader.setController(). Если вы создадите экземпляр класса контроллера самостоятельно, эти аннотированные поля @FXML будут пустыми. Так вот пример подход для использования setController() вместо Fx: контроллер в FXML файле:

MainApp

public class MainApp extends Application 
{ 
    @Override 
    public void start(Stage stage) throws Exception 
    { 
     MainController mainController = new MainController(getConnection()); 

     Scene scene = new Scene(mainController.getLayout()); 

     stage.setScene(scene); 
     stage.show(); 
    } 


    public static void main(String[] args) 
    { 
     launch(args); 
    } 
} 

MainController

public class MainController implements Initializable 
{ 

    @FXML 
    private Label label; 

    private Parent layout; 

    private Connection connection; 


    public MainController(Connection connection) 
    { 
     this.connection = connection; 

     FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Main.fxml")); 
     fxmlLoader.setController(this); 
     try 
     { 
      layout = (Parent) fxmlLoader.load(); 
     } 
     catch (IOException exception) 
     { 
      throw new RuntimeException(exception); 
     } 
    } 


    public Parent getLayout() 
    { 
     return layout; 
    } 


    @FXML 
    private void handleTableView(ActionEvent event) 
    { 
     InterfaceMethods iMethods = new InterfaceMethods(connection); 
     label.getScene().setRoot(iMethods.getLayout()); 
     label.getScene().getWindow().sizeToScene(); 
    } 


    @Override 
    public void initialize(URL url, ResourceBundle rb) 
    { 
     // do work with @FXML annotated fields in here 
     label.setText("Initial data!"); 
    } 

} 

Main.fxml

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

<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1"> 
    <children> 
     <Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleTableView" fx:id="button" /> 
     <Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" /> 
    </children> 
</AnchorPane> 

InterfaceMethods

public class InterfaceMethods implements Initializable 
{ 

    @FXML 
    TableView<Job> tView; 

    private Parent layout; 

    private Connection connection; 


    public MainController(Connection connection) 
    { 
     this.connection = connection; 

     FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("TableViewInterface.fxml")); 
     fxmlLoader.setController(this); 
     try 
     { 
      layout = (Parent) fxmlLoader.load(); 
     } 
     catch (IOException exception) 
     { 
      throw new RuntimeException(exception); 
     } 
    } 


    public Parent getLayout() 
    { 
     return layout; 
    } 

    @Override 
    public void initialize(URL url, ResourceBundle rb) 
    { 
     // do work with @FXML annotated fields in here 
     tView.setItems(...); 
    } 

} 

Обратите внимание, что Main.fxml и TableViewInterface.fxml не fx:controller в нем.

+0

Я не уверен, что на 100% понимаю проблему, но я ценю вашу помощь. Я продолжу читать учебники и смотреть видео, чтобы, надеюсь, лучше понять эту ситуацию. – jbanks

+0

Проблема заключалась в iMethods = new InterfaceMethods(); в вашем коде. Вы должны использовать FXMLloader и получить экземпляр conrtoller из fxmlloader, а не инициировать его самостоятельно, если вы используете подход fx: conrtoller. Если нет, вы можете следовать подходу, как в моем ответе, используя setConrtoller() и самостоятельно инициализировать класс conrtoller. –

+0

@jbanks, еще одна проблема заключается в методе populateTableView(), который вы загружаете «TableViewInterface.fxml "с fxmlloader.Это создаст новые InterfaceMethods и заполнит его поле tView, тогда как tView текущего экземпляра ** будет null, и поэтому NPE. –

Смежные вопросы