Reputation: 63
I keep getting a java.lang.NullPointerException when running case 0 on run time. The issue seems to be linked to setting the prompt text for my TextField. However, the problem doesn't return when I switch tabs. The GUI was built in Scene Builder. How do i initialize the TextField to a non-null value.
public class BackEndController implements Initializable{
@FXML
private TabPane tabPane;
@FXML
private Tab bookingTab;
@FXML
private Tab waitListTab;
@FXML
private Tab excursionsTab;
@FXML
private TextField searchEntry;
@Override
public void initialize(URL location, ResourceBundle resources) {
searchEntry.setPromptText("");
}
@FXML
public void switchTabs() {
int selectedTab = tabPane.getSelectionModel().getSelectedIndex();
switch (selectedTab){
case 0:
searchEntry.setPromptText("Enter booking ID");
break;
case 1:
searchEntry.setPromptText("Enter event name");
break;
case 2:
searchEntry.setPromptText("Enter list ID");
break;
}
}
This is the exact error code
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1787)
at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.controls/javafx.scene.control.Tab$1.invalidated(Tab.java:215)
at javafx.base/javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
at javafx.base/javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145)
at javafx.controls/javafx.scene.control.Tab.setSelected(Tab.java:189)
at javafx.controls/javafx.scene.control.TabPane$TabPaneSelectionModel.select(TabPane.java:738)
at javafx.controls/javafx.scene.control.TabPane$TabPaneSelectionModel.select(TabPane.java:751)
at javafx.controls/javafx.scene.control.TabPane$TabPaneSelectionModel.findNearestAvailableTab(TabPane.java:810)
at javafx.controls/javafx.scene.control.TabPane$TabPaneSelectionModel.lambda$new$0(TabPane.java:707)
at javafx.base/com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
at javafx.base/com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at javafx.base/javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.base/javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
at javafx.base/javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.base/javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at javafx.base/javafx.collections.ModifiableObservableListBase.add(ModifiableObservableListBase.java:155)
at java.base/java.util.AbstractList.add(AbstractList.java:111)
at javafx.fxml/javafx.fxml.FXMLLoader$Element.add(FXMLLoader.java:175)
at javafx.fxml/javafx.fxml.FXMLLoader$PropertyElement.add(FXMLLoader.java:1415)
at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:796)
at javafx.fxml/javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2838)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2557)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3253)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3210)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3179)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3152)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3129)
at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3122)
at com.main.backend.BackEnd.start(BackEnd.java:18)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:919)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)
at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1784)
... 47 more
Caused by: java.lang.NullPointerException
at com.main.backend.BackEndController.switchTabs(BackEndController.java:58)
... 59 more
My FXML file
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXListView?>
<?import com.jfoenix.controls.JFXTabPane?>
<?import com.jfoenix.controls.JFXTextField?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="810.0" prefWidth="1250.0" style="-fx-background-color: #FFFFFF;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.main.backend.BackEndController">
<children>
<JFXTabPane fx:id="tabPane" layoutY="67.0" prefHeight="743.0" prefWidth="1250.0" stylesheets="@dark-theme.css">
<tabs>
<Tab fx:id="bookingTab" onSelectionChanged="#switchTabs" text="Bookings">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" style="-fx-background-color: #F7F7F9;" />
</content>
</Tab>
<Tab fx:id="excursionsTab" onSelectionChanged="#switchTabs" text="Excursions">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" style="-fx-background-color: #F7F7F9;">
<children>
<AnchorPane layoutX="736.0" layoutY="16.0" prefHeight="672.0" prefWidth="501.0" style="-fx-background-color: #FFFFFF; -fx-border-color: #D4D6D8;">
<children>
<JFXTextField alignment="CENTER" layoutX="17.0" layoutY="85.0" prefHeight="33.0" prefWidth="135.0" promptText="Port ID" styleClass="main-text" stylesheets="@dark-theme.css">
<font>
<Font name="System Bold" size="15.0" />
</font>
</JFXTextField>
<Label alignment="CENTER" layoutX="12.0" layoutY="33.0" prefHeight="33.0" prefWidth="478.0" text="Label" textFill="#9f9f9f">
<font>
<Font name="System Bold" size="15.0" />
</font>
</Label>
<JFXButton layoutX="265.0" layoutY="178.0" prefHeight="33.0" prefWidth="174.0" style="-fx-background-color: #FA597A; -fx-border-color: #FA597A; -fx-border-radius: 30; -fx-background-radius: 30;" text="Delete Event" textFill="WHITE">
<font>
<Font name="System Bold" size="15.0" />
</font>
</JFXButton>
<JFXButton layoutX="17.0" layoutY="178.0" prefHeight="33.0" prefWidth="185.0" style="-fx-background-color: #FFFFFF; -fx-border-color: #214099; -fx-border-radius: 30; -fx-background-radius: 30;" text="Update Event" textFill="#214099">
<font>
<Font name="System Bold" size="15.0" />
</font>
</JFXButton>
<Separator layoutX="21.0" layoutY="272.0" prefHeight="13.0" prefWidth="460.0" />
<JFXTextField alignment="CENTER" layoutX="17.0" layoutY="321.0" prefHeight="33.0" prefWidth="468.0" promptText="Event Name" styleClass="main-text" stylesheets="@dark-theme.css">
<font>
<Font name="System Bold" size="15.0" />
</font>
</JFXTextField>
<JFXTextField alignment="CENTER" layoutX="19.0" layoutY="396.0" prefHeight="33.0" prefWidth="135.0" promptText="Port ID" styleClass="main-text" stylesheets="@dark-theme.css">
<font>
<Font name="System Bold" size="15.0" />
</font>
</JFXTextField>
<JFXButton layoutX="173.0" layoutY="470.0" prefHeight="33.0" prefWidth="185.0" style="-fx-background-color: #FFFFFF; -fx-border-color: #15d31e; -fx-border-radius: 30; -fx-background-radius: 30;" text="Add Event" textFill="#15d31e">
<font>
<Font name="System Bold" size="15.0" />
</font>
</JFXButton>
</children>
</AnchorPane>
<JFXListView fx:id="excursionsList" layoutX="16.0" layoutY="16.0" prefHeight="672.0" prefWidth="711.0" styleClass="list-cell" stylesheets="@dark-theme.css" />
</children>
</AnchorPane>
</content>
</Tab>
<Tab fx:id="waitListTab" onSelectionChanged="#switchTabs" text="Waiting List">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" style="-fx-background-color: #F7F7F9;" />
</content>
</Tab>
</tabs>
</JFXTabPane>
<JFXButton layoutX="609.0" layoutY="18.0" prefHeight="32.0" prefWidth="110.0" style="-fx-background-color: #214099; -fx-border-color: #214099; -fx-border-radius: 30; -fx-background-radius: 30;" text="Search" textFill="WHITE">
<font>
<Font name="System Bold" size="15.0" />
</font>
</JFXButton>
<JFXButton layoutX="740.0" layoutY="18.0" prefHeight="32.0" prefWidth="99.0" style="-fx-background-color: #FFFFFF; -fx-border-color: #214099; -fx-border-radius: 30; -fx-background-radius: 30;" text="Reset" textFill="#214099">
<font>
<Font name="System Bold" size="15.0" />
</font>
</JFXButton>
<JFXButton layoutX="1113.0" layoutY="18.0" prefHeight="32.0" prefWidth="116.0" style="-fx-background-color: #FA597A; -fx-border-color: #FA597A; -fx-border-radius: 30; -fx-background-radius: 30;" text="Sign Out" textFill="WHITE">
<font>
<Font name="System Bold" size="15.0" />
</font>
</JFXButton>
<JFXTextField fx:id="searchEntry" layoutX="104.0" layoutY="20.0" prefHeight="32.0" prefWidth="449.0" promptText="Enter booking ID" styleClass="search-textfield" stylesheets="@dark-theme.css">
<font>
<Font name="System Bold" size="15.0" />
</font>
</JFXTextField>
</children>
</AnchorPane>
The FXML file does have the correct controller attached
Upvotes: 2
Views: 1321
Reputation: 209330
As the FXML is parsed, the FXMLLoader
creates the TabPane
, and creates the Tab
s and adds them to the TabPane
. When the first tab is added, it becomes selected, so its selected
state changes and its onSelectionChanged
handler is invoked. Since the TabPane
appears in the FXML file before the searchEntry
text field, this happens before searchEntry
is initialized, and consequently your switchTabs()
method throws a null pointer exception.
You could simply add a null check to the handler method:
@FXML
public void switchTabs() {
if (searchEntry == null) {
return ;
}
int selectedTab = tabPane.getSelectionModel().getSelectedIndex();
switch (selectedTab){
case 0:
searchEntry.setPromptText("Enter booking ID");
break;
case 1:
searchEntry.setPromptText("Enter event name");
break;
case 2:
searchEntry.setPromptText("Enter list ID");
break;
}
}
Adding this code just to handle a special case that only occurs during loading is a little ugly. I would prefer just to register a handler in the initalize()
method. Remove all the onSelectionChanged
handlers from the tabs in the FXML file, and add the following to your controller's initialize()
method:
@Override
public void initialize(URL location, ResourceBundle resources) {
tabPane.getSelectionModel().selectedIndexProperty().addListener(
(obs, oldIndex, newIndex) -> switchTabs());
// initialize prompt text for initially-selected tab:
switchTabs();
// searchEntry.setPromptText("");
}
Upvotes: 2