每当我尝试从另一个类的Executor重新填充TableView中的元素时,我会收到以下错误:
MainController Init prints main.getCurrentTime = 2017-07-31T22:31:37.969
*** MainController Initialized ***
**** createAndStartScheduler ****
repeat every 2
Platform.isFxApplicationThread() = true
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at testpackage.MainController.populateTable(MainController.java:107)
at testpackage.Refresh.lambda$null$0(Refresh.java:41)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
MainController.java
107处的错误:nameCol.setCellValueFactory(new PropertyValueFactory<>(“name”));
@FXML // fx:id="tableView"
private TableView<Item> tableView; // Value injected by FXMLLoader
@FXML // fx:id="statusCol"
private TableColumn<Item, Boolean> statusCol; // Value injected by FXMLLoader
@FXML // fx:id="dateCol"
// USing string to display it because SimpleDateFormat.format returns a string
private TableColumn<Item, String> dateCol; // Value injected by FXMLLoader
@FXML // fx:id="nameCol"
private TableColumn<Item, String> nameCol; // Value injected by FXMLLoader
@FXML // fx:id="urlCol"
private TableColumn<Item, Hyperlink> urlCol; // Value injected by FXMLLoader
public void initialize() {
GimmeTheFreeStuff gimmeTheFreeStuff = new GimmeTheFreeStuff();
GetSetProps getSetProps = new GetSetProps();
System.out.println(
"MainController Init prints main.getCurrentTime = " + Main.getCurrentTime().toString());
// testLink is called twice in the try
try {
Main.getStage()
.setTitle("GimmeTheFreeStuff for " + gimmeTheFreeStuff.getTitle(getSetProps.getLink()));
populateTable("");
} catch (IOException e) {
System.err.println("Unable to set the title OR Unable to populate table");
e.printStackTrace();
}
System.out.println("*** MainController Initialized ***");
}
public void populateTable(String temp) throws IOException {
nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
dateCol.setCellValueFactory(new PropertyValueFactory<>("date"));
urlCol.setCellValueFactory(new PropertyValueFactory<>("urlLink"));
statusCol.setCellValueFactory(new PropertyValueFactory<>("status"));
ObservableList<Item> oList =
FXCollections.observableArrayList(parseItemList(temp));
tableView.getItems().setAll(oList);
success();
}
Refresh.java
41处的错误:mainController.populateTable(“”);
static void createAndStartScheduler() throws IOException {
scheduler = Executors.newSingleThreadScheduledExecutor();
System.out.println("**** createAndStartScheduler **** ");
long delay = 2;
scheduler.scheduleAtFixedRate(() -> Platform.runLater(() -> {
MainController mainController = new MainController();
System.out.println("repeat every " + delay);
System.out.println("Platform.isFxApplicationThread() = " + Platform
.isFxApplicationThread()); // returns True
try {
mainController.populateTable("");
} catch (IOException e) {
e.printStackTrace();
}
}), delay, delay, TimeUnit.SECONDS);
}
由于它的NullPointerException意味着在错误118处,PropertyValueFactory“name”为null或nameCol出错。我读过的大部分答案都涉及使用Platform.runLater。我认为最接近我的问题是:JavaFX: Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
我会假设我必须以某种方式重新初始化nameCol,dateCol等?
编辑#2(找到解决方案):
感谢Scary Wombat简单的调试建议,我添加了if(namCol == null){System.out.print(“nameCol is null”);返回;} nameCol确实是null b / c FXMLLoader初始化MainController.fxml的UI元素,并且创建MainController.java的新实例不会做任何事情。所以我只需要从Main.java获取控制器的FXMLLoader实例并使用它来更新我的TableView。
Main.java
FXMLLoader loader = new FXMLLoader(getClass().getResource("MainUserInterface.fxml"));
Parent root = loader.load();
MainController controller = loader.getController();
Refresh refresh = new Refresh();
refresh.setObj(controller);
Refresh.java
private static MainController obj;
public static MainController getObj() { return obj;}
public static void setObj(MainController obj) { Refresh.obj = obj;}
// used getObj() to update tableview instead of creating new instance of MainController
希望这有助于其他人!