I'm a new javaFx with Scenebuilder and MVC starter.
I have a problem as below:
I tried to make a main window to alert a new window. And I tried to midified the label text in that alert window. But I cannot do that. And I got this error:
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
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.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:8411)
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.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:3757)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
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$355(GlassViewEventHandler.java:388)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$149(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
... 48 more
Caused by: java.lang.NullPointerException
at controller.AlertController.setAlertLabel(AlertController.java:36)
at controller.MainController.onMainButtonClicked(MainController.java:24)
... 58 more
I have a main window with maincontroller, alertController and main.fxml and alert.fxml as below:
Main:
package app;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("../view/Main.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Main Controller:
package controller;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
public class MainController {
AlertController alertController = new AlertController();
#FXML
public Label mainLabel;
#FXML
public TextField mainTextField;
#FXML
public Button mainButton;
#FXML
public void onMainButtonClicked() {
alertController.displayAlert();
alertController.setAlertLabel("Hello from MainController!");
}
}
Main.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.MainController">
<children>
<VBox prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<HBox alignment="CENTER" prefHeight="154.0" prefWidth="600.0">
<children>
<Label fx:id="mainLabel" alignment="CENTER" contentDisplay="TOP" prefHeight="31.0" prefWidth="115.0" text="Main Text" />
</children>
</HBox>
<HBox alignment="CENTER" centerShape="false" layoutX="10.0" layoutY="10.0">
<children>
<TextField fx:id="mainTextField" alignment="TOP_LEFT" prefHeight="25.0" prefWidth="331.0" />
</children>
</HBox>
<HBox alignment="CENTER" layoutX="10.0" layoutY="10.0" prefHeight="100.0" prefWidth="200.0">
<children>
<Button fx:id="mainButton" mnemonicParsing="false" onAction="#onMainButtonClicked" text="Display Alert && Set Message Text" />
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>
AlertController:
package controller;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import java.io.IOException;
public class AlertController {
Stage window;
#FXML
public Label alertLabel;
#FXML
Button alertButton;
public void displayAlert() {
try {
window = new Stage();
Parent root = FXMLLoader.load(getClass().getResource("../view/Alert.fxml"));
Scene scene = new Scene(root);
window.setScene(scene);
window.setTitle("Alert");
window.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public void setAlertLabel(String str) {
alertLabel.setText(str);
}
#FXML
public void onAlertButtonClicked() {
window.close();
}
}
And Alert.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="210.0" prefWidth="380.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.AlertController">
<children>
<VBox prefHeight="210.0" prefWidth="380.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<HBox alignment="BOTTOM_CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Label fx:id="alertLabel" text="Alert Message" />
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Button fx:id="alertButton" mnemonicParsing="false" onAction="#onAlertButtonClicked" text="Close" />
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>
Please kindly help me solve this problems and explain me why this doesn't work. Thank you for you suggestions.
There are two instances of AlertController: the one you create in MainController with
AlertController alertController = new AlertController();
and the one that is created by the FXMLLoader when you load Alert.fxml in displayAlert().
The #FXML-annotated fields are initialized by the FXMLLoader on the instance it creates. However, you are calling setAlertLabel(...) on an instance of AlertController that was not created by the FXMLLoader. So when you call
alertController.setAlertLabel("Hello from MainController!");
the alertLabel belonging to alertController has not been initialized, and you get a null pointer exception.
Simple Solution
The easiest fix is to load Alert.fxml in MainController, and retrieve the correct controller instance:
public class MainController {
#FXML
public Label mainLabel;
#FXML
public TextField mainTextField;
#FXML
public Button mainButton;
#FXML
public void onMainButtonClicked() {
FXMLLoader loader = new FXMLLoader(getClass().getResource("../view/Alert.fxml"));
Parent root = loader.load();
AlertController alertController = loader.getController();
alertController.setAlertLabel("Hello from MainController!");
Scene scene = new Scene(root);
window.setScene(scene);
window.setTitle("Alert");
window.show();
}
}
and remove the displayAlert() method from AlertController.
Custom Component Solution
An alternative, which is structurally a bit closer to your original, is to replace the AlertController with a custom component.
Alert.fxml (note the change to the root element, and that fx:controller has been removed):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<fx:root type="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="210.0" prefWidth="380.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" >
<children>
<VBox prefHeight="210.0" prefWidth="380.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<HBox alignment="BOTTOM_CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Label fx:id="alertLabel" text="Alert Message" />
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Button fx:id="alertButton" mnemonicParsing="false" onAction="#onAlertButtonClicked" text="Close" />
</children>
</HBox>
</children>
</VBox>
</children>
</fx:root>
AlertController.java:
package controller;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import java.io.IOException;
public class AlertController extends AnchorPane {
Stage window;
#FXML
public Label alertLabel;
#FXML
Button alertButton;
public AlertController() {
window = new Stage();
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("../view/Alert.fxml"));
loader.setController(this);
loader.setRoot(this);
loader.load();
Scene scene = new Scene(this);
window.setScene(scene);
window.setTitle("Alert");
} catch (IOException e) {
e.printStackTrace();
}
}
public void displayAlert() {
window.show();
}
public void setAlertLabel(String str) {
alertLabel.setText(str);
}
#FXML
public void onAlertButtonClicked() {
window.close();
}
}
and now your main controller can look like this:
package controller;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
public class MainController {
AlertController alertController = new AlertController();
#FXML
public Label mainLabel;
#FXML
public TextField mainTextField;
#FXML
public Button mainButton;
#FXML
public void onMainButtonClicked() {
alertController.displayAlert();
alertController.setAlertLabel("Hello from MainController!");
}
}
Related
I have a problem with getting to the Controller.
I have a main template with two parts: Menu and Main Content
In two separate FXML files I have the Menu (MenuTemplate.fxml) and Main Content (Content1Template.fxml).
The loading of the Menu and Main Content proceeds correctly
The problem appears when Main Content wants to change the text after pressing the button.
Content1Utils.java has to set text in Content1Controller.java.
I guess I have to get to the controller. I just have a problem how to do it.
Link >> My Project in rar
Luncher.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import sample.main.MainController;
import java.io.File;
import java.net.URL;
public class Launcher extends Application {
private static MainController mainController;
#Override
public void start(Stage primaryStage) throws Exception{
URL mainTemplate = new File("src/sample/main/MainTemplate.fxml").toURI().toURL();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(mainTemplate);
Parent root = loader.load();
mainController = loader.getController();
Scene scene = new Scene(root);
primaryStage.setTitle("Hello World");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public MainController getMainController(){
return mainController;
}
}
MainController.java
package sample.main;
import com.jfoenix.controls.JFXDrawer;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.VBox;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class MainController {
#FXML private VBox rootBox;
#FXML private JFXDrawer menuBox;
#FXML private VBox contentBox;
#FXML
void initialize() throws IOException {
URL menuTemplate = new File("src/sample/menu/MenuTemplate.fxml").toURI().toURL();
VBox contentMenu = FXMLLoader.load(menuTemplate);
menuBox.setContent(contentMenu);
}
public void changeContentBox(VBox content){
contentBox.getChildren().setAll(content);
}
}
MenuController.java
package sample.menu;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import sample.Launcher;
import sample.main.MainController;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class MenuController {
#FXML private VBox menuRoot;
#FXML private Button menuButton1;
#FXML private Button menuButton2;
#FXML private Button menuButton3;
private MainController mainController;
#FXML
void initialize(){
}
public void clickButton1() throws IOException {
URL content1Template = new File("src/sample/content1/Content1Template.fxml").toURI().toURL();
VBox contentContent1 = FXMLLoader.load(content1Template);
mainController = new Launcher().getMainController();
mainController.changeContentBox(contentContent1);
}
}
Content1Controller.java
package sample.content1;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
public class Content1Controller {
#FXML private VBox content1root;
#FXML private Button content1Button;
#FXML private TextArea content1TextArea;
#FXML
void initialize(){
}
public void content1Button(){
Content1Utils contentUtils = new Content1Utils();
contentUtils.prepareText("XXX");
}
public void setTextInArea(String txt){
content1TextArea.setText(txt);
}
}
Content1Utils.java
package sample.content1;
public class Content1Utils {
public void prepareText(String txt){
String newTxt = txt + " - Test123";
new Content1Controller().setTextInArea(newTxt);
}
}
MainTemplate.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXDrawer?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox fx:id="rootBox" prefHeight="442.0" prefWidth="665.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.main.MainController">
<children>
<HBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" VBox.vgrow="ALWAYS">
<children>
<JFXDrawer fx:id="menuBox" style="-fx-background-color: #ebd534;" />
<VBox fx:id="contentBox" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" style="-fx-background-color: #34b7eb;" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</children>
</VBox>
MenuTemplate.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.VBox?>
<VBox fx:id="menuRoot" prefHeight="442.0" prefWidth="100.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.menu.MenuController">
<children>
<Button fx:id="menuButton1" maxHeight="100.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#clickButton1" text="Button 1" VBox.vgrow="ALWAYS" />
<Button fx:id="menuButton2" maxHeight="100.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Button 2" VBox.vgrow="ALWAYS" />
<Button fx:id="menuButton3" maxHeight="100.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Button3" VBox.vgrow="ALWAYS" />
</children>
</VBox>
Content1Template.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.VBox?>
<VBox fx:id="content1root" alignment="CENTER" prefHeight="442.0" prefWidth="565.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.content1.Content1Controller">
<children>
<Button fx:id="content1Button" contentDisplay="CENTER" mnemonicParsing="false" onAction="#content1Button" prefHeight="48.0" prefWidth="400.0" text="Button" textAlignment="CENTER">
<VBox.margin>
<Insets />
</VBox.margin>
</Button>
<TextArea fx:id="content1TextArea" maxWidth="400.0" prefHeight="200.0" prefWidth="400.0">
<VBox.margin>
<Insets top="10.0" />
</VBox.margin>
</TextArea>
</children>
</VBox>
ERROR
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
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 javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:432)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
... 48 more
Caused by: java.lang.NullPointerException
at sample.content1.Content1Controller.setTextInArea(Content1Controller.java:25)
at sample.content1.Content1Utils.prepareText(Content1Utils.java:8)
at sample.content1.Content1Controller.content1Button(Content1Controller.java:21)
... 58 more
The problem is here:
public class Content1Utils {
public void prepareText(String txt){
String newTxt = txt + " - Test123";
new Content1Controller().setTextInArea(newTxt);
}
}
You are making a new controller instance that is not initialized from the FXML so it doesn't have a valid TextArea field. You don't want to have your utility class work this way.
Try:
public void content1Button(){
Content1Utils contentUtils = new Content1Utils(this);
contentUtils.prepareText("XXX");
}
Content1Utils.java:
package sample.content1;
public class Content1Utils {
private final Content1Controller controller;
public Content1utils(Content1Controller ctrl) {
this.controller = ctrl;
}
public void prepareText(String txt){
String newTxt = txt + " - Test123";
controller.setTextInArea(newTxt);
}
}
Now I'm making a project about File Manager software by JavaFX but a plenty of error occur.
I have some class:
File Main.java
package QLF;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application
{
#Override
public void start(Stage primaryStage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("LogIn.fxml"));
Scene scene = new Scene(root);
primaryStage.setTitle("Hello World");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
File Controller.java
package QLF;
import javafx.scene.control.*;
import javafx.fxml.*;
import javafx.event.*;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable
{
#FXML
private Button btnSignIn;
#FXML
private Button btnQuit;
#FXML
private TextField txtUserName;
#FXML
private PasswordField txtPassword;
#FXML
private Label lblUStatus;
#FXML
private Label lblPStatus;
#FXML
private void handleEvent(ActionEvent event)
{
if(event.getSource() == btnSignIn)
{
//check 'null'
if(txtUserName.getText().equals(null))
{
lblUStatus.setVisible(true);
lblUStatus.setText("You have to enter your Username or your Email");
}
else if(txtPassword.getText().equals(null))
{
lblPStatus.setVisible(true);
lblPStatus.setText("You have to enter your Password");
}
}
if(event.getSource() == btnQuit)
{
}
}
#Override
public void initialize(URL location, ResourceBundle resources)
{
}
}
File LogIn.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Label?> <?import javafx.scene.control.PasswordField?> <?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="376.167" prefWidth="614.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="QLF.Controller">
<children>
<Label id="title" layoutX="141.0" layoutY="55.0" prefHeight="73.0" prefWidth="315.0" text="Log-In to QLF">
<font>
<Font size="50.0" />
</font>
</Label>
<TextField id="txtUserName" fx:id="txtUserName" layoutX="50.0" layoutY="150.0" prefHeight="25.0" prefWidth="521.0" promptText="Username*" />
<Button id="btnSignIn" fx:id="btnSignIn" layoutX="50.0" layoutY="302.0" mnemonicParsing="false" onMouseClicked="#handleEvent" prefHeight="25.0" prefWidth="109.0" text="Sign-In" />
<Button id="btnQuit" fx:id="btnQuit" layoutX="462.0" layoutY="302.0" mnemonicParsing="false" onMouseClicked="#handleEvent" prefHeight="25.0" prefWidth="109.0" text="Quit" />
<PasswordField id="txtPassword" fx:id="txtPassword" layoutX="50.0" layoutY="243.0" prefHeight="25.0" prefWidth="521.0" promptText="Password*" />
<Label fx:id="lblUStatus" layoutX="50.0" layoutY="180.0" prefHeight="17.0" prefWidth="33.0" text="Status" textFill="RED" visible="false" />
<Label fx:id="lblPStatus" layoutX="53.0" layoutY="274.0" text="Status" textFill="#f50000" visible="false" />
</children>
</AnchorPane>
Error
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
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.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$ClickGenerator.postProcess(Scene.java:3470)
at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3766)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:417)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
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:748)
onMouseClicked events cause MouseEvents not ActionEvents. Since MouseEvent cannot be cast to ActionEvent, handleEvent cannot handle MouseEvents.
Use the onAction event handler instead:
...
<Button ... onAction="#handleEvent" ... text="Sign-In" />
<Button ... onAction="#handleEvent" ... text="Quit" />
...
Introduction:
This is simply a "Table" where cards can be "placed" on, by right clicking on the table.
I have 2 FXML objects:
Card
UI
Problem:
In short, a Card needs to be added to the UI "Table", this is where my problem lies.
The adding Card method simply adds the card to a Pane object (which is not null), and we know that Pane's add objects which extend a Node
I tried 2 solutions, of which both failed.
Solution 1
Using the FXMLLoader to load the Card.fxml file into a Card object:
Having the Card definition as follows
public class Card implements Initializable
causes issues:
FXMLLoader loader = new FXMLLoader(getClass().getResource("/Layouts/Card.fxml"));
Card card = loader.load();
card.setLayoutX(mouseEvent.getSceneX() - (card.getLayoutX() / 2)); <--------here setLayoutX
card.setLayoutY(mouseEvent.getSceneY() - (card.getLayoutY() / 2)); <--------here setLayoutY
card.isFaceDown.addListener((observable, oldValue, newValue) -> {
if (newValue) {
facedownCount.add(1);
} else {
facedownCount.subtract(1);
}
});
totalCount.add(1);
gamePane.getChildren().add(card); <--------here card does not extend Node
The issue is I am unable to set layout properties of the Card object if it doesn't extend a stackpane, and also I am unable to add it to another object as a child
Solution 2: (more likely to be correct)
Changing the Card definition to
public class Card extends StackPane implements Initializable
followed by attempting to add it:
FXMLLoader loader = new FXMLLoader(getClass().getResource("/Layouts/Card.fxml"));
Card card = loader.load(); < -------- PROBLEM
which gives me this exception error:
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
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.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:3757)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:417)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769)
... 29 more
Caused by: java.lang.ClassCastException: javafx.scene.layout.StackPane cannot be cast to Game.Controller.Card
at Game.Controller.UI.HandleClick(UI.java:60)
... 39 more
Card.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.effect.DropShadow?>
<StackPane maxHeight="-Infinity"
maxWidth="-Infinity"
minHeight="-Infinity"
minWidth="-Infinity"
prefHeight="400.0"
prefWidth="600.0"
xmlns="http://javafx.com/javafx/8.0.112"
fx:controller="Game.Controller.Card"
xmlns:fx="http://javafx.com/fxml/1">
<children>
<ImageView fx:id="imgSuit" fitHeight="275.0" fitWidth="183.0" layoutX="10.0" layoutY="10.0" pickOnBounds="true" preserveRatio="true" />
<ImageView fx:id="imgValue" fitHeight="275.0" fitWidth="183.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#../suits/back.png" />
</image>
</ImageView>
</children>
<effect>
<DropShadow />
</effect>
</StackPane>
Card Controller
public class Card implements Initializable {
public static HashMap cardSuit, cardValue;
public BooleanProperty isFaceDown = new SimpleBooleanProperty(true);
private IntegerProperty value = new SimpleIntegerProperty(-1);
public StringProperty suit = new SimpleStringProperty("");
public ImageView imgValue = new ImageView();
public ImageView imgSuit = new ImageView();
public Card(){
super();
}
#Override
public void initialize(URL location, ResourceBundle resources) {
initImages();
setupBindings();
setDefaults();
}
private void setDefaults() {
isFaceDown.set(true);
}
private void setupBindings() {
isFaceDown.addListener((observable, oldValue, newValue) -> {
if (newValue){
imgValue.setImage(null);
imgSuit.setImage((Image) cardSuit.get("B"));
}
else {
imgValue.setImage((Image) cardValue.get(value.get()));
imgSuit.setImage((Image) cardSuit.get(suit.get()));
}
});
}
private void initImages() {
if (cardSuit == null) {
cardSuit = new HashMap<String, Image>();
cardSuit.put("B", new Image("/suits/back.png"));
cardSuit.put("C", new Image("/suits/clubs.png"));
cardSuit.put("D", new Image("/suits/diamonds.png"));
cardSuit.put("S", new Image("/suits/spades.png"));
cardSuit.put("H", new Image("/suits/hearts.png"));
}
if (cardValue == null) {
cardValue = new HashMap<Integer, Image>();
for (int i = 1; i <= 13; i++) {
cardValue.put(i, new Image("/values/" + String.valueOf(i) + ".png"));
}
}
}
}
UI fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onMousePressed="#HandleClick" prefHeight="750.0" prefWidth="702.0" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Game.Controller.UI">
<children>
<MenuBar prefHeight="29.0" prefWidth="700.0">
<menus>
<Menu mnemonicParsing="false" text="Menu">
<items>
<MenuItem fx:id="mmReset" mnemonicParsing="false" text="Reset" />
<MenuItem fx:id="mmClose" mnemonicParsing="false" onAction="#CloseApp" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem fx:id="mmAbout" mnemonicParsing="false" text="About" />
</items>
</Menu>
<Menu fx:id="mInstruct" mnemonicParsing="false" text="Instructions" />
</menus>
</MenuBar>
<StackPane fx:id="gamePane" layoutX="1.0" layoutY="29.0" prefHeight="700.0" prefWidth="700.0" style="-fx-background-color: green;" />
<HBox layoutX="7.0" layoutY="731.0" prefHeight="15.0" prefWidth="693.0">
<children>
<Label fx:id="lblHearts" text="Hearts = " />
<Label fx:id="lblDiamonds" text="Diamonds = " />
<Label fx:id="lblSpades" text="Spades = " />
<Label fx:id="lblClubs" text="Clubs = " />
<Label fx:id="lblFaceUp" text="Facing Up =" />
</children>
</HBox>
</children>
</AnchorPane>
What am I doing wrong, I think that solution #2 is more 'correct', but why doesn't the loader allow loading into the Card, with the StackPane cast exception
p.s. As a sub question, what difference does the root node make in this case, when loading the fxml object, will it allow me to e.g. setlayoutX property if I don't explicitly extends StackPane in the definition?
You could create a custom component that extends StackPane and is used as the controller class controller by using the <fx:root> element
public class Card extends StackPane implements Initializable {
public Card() {
FXMLLoader loader = new FXMLLoader(getClass().getResouce("card.fxml"));
loader.setRoot(this);
loader.setController(this);
try {
loader.load();
} catch (Exception e) {
throw new IllegalStateException("Could not load fxml", e);
}
}
...
}
card.fxml
<fx:root type="javafx.scene.layout.StackPane"
maxHeight="-Infinity"
maxWidth="-Infinity"
minHeight="-Infinity"
minWidth="-Infinity"
prefHeight="400.0"
prefWidth="600.0"
xmlns="http://javafx.com/javafx/8.0.112"
xmlns:fx="http://javafx.com/fxml/1">
<children>
<ImageView fx:id="imgSuit" fitHeight="275.0" fitWidth="183.0" layoutX="10.0" layoutY="10.0" pickOnBounds="true" preserveRatio="true" />
<ImageView fx:id="imgValue" fitHeight="275.0" fitWidth="183.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#../suits/back.png" />
</image>
</ImageView>
</children>
<effect>
<DropShadow />
</effect>
</fx:root>
Currently i have TabPane with 3 active tabs. I have to manually switch between them, which isn't ideal. What i would like to do is replace the TabPane all together and have one scene inside the stage, which would then switch to next scene (From Tab1, to Tab2, to Tab3) upon press of a button.
It is important to maintain the set label text functionality.
Tab1
Tab2
Main.java
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("../view/Main.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
MainController.java
package controller;
import javafx.fxml.FXML;
import controller.tab.Tab1Controller;
import controller.tab.Tab2Controller;
import controller.tab.Tab3Controller;
public class MainController {
#FXML Tab1Controller tab1Controller;
#FXML Tab2Controller tab2Controller;
#FXML Tab3Controller tab3Controller;
public void initialize() {
tab1Controller.init(this);
tab2Controller.init(this);
tab3Controller.init(this);
}
public void setTab2LabelText(String text) {
tab3Controller.lbl3.setText(text);
tab2Controller.lbl2.setText(text);
}
}
Tab1Controller.java
package controller.tab;
import controller.MainController;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import java.io.IOException;
public class Tab1Controller {
private MainController main;
#FXML public Label lbl1;
#FXML private Button btn1Send;
#FXML private void btn1SendClicked(ActionEvent event) throws IOException {
main.setTab2LabelText("abc");
}
public void init(MainController mainController) {
main = mainController;
}
}
Tab2Controller.java
package controller.tab;
import controller.MainController;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class Tab2Controller {
private MainController main;
#FXML public Label lbl2;
public void init(MainController mainController) {
main = mainController;
}
}
Tab3Controller.java
package controller.tab;
import controller.MainController;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class Tab3Controller {
private MainController main;
#FXML public Label lbl3;
public void init(MainController mainController) {
main = mainController;
}
}
Main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="432.0" prefWidth="443.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.MainController">
<children>
<TabPane prefHeight="299.0" prefWidth="309.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<tabs>
<Tab closable="false" text="Tab 1">
<content>
<fx:include fx:id="tab1" source="tab/Tab1.fxml" />
</content></Tab>
<Tab closable="false" text="Tab 2">
<content>
<fx:include fx:id="tab2" source="tab/Tab2.fxml" />
</content></Tab>
<Tab closable="false" text="Tab 3">
<content>
<fx:include fx:id="tab3" source="tab/Tab3.fxml" />
</content></Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
Tab2.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="206.0" prefWidth="226.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.tab.Tab1Controller">
<children>
<Button fx:id="btn1Send" layoutX="42.0" layoutY="74.0" mnemonicParsing="false" onAction="#btn1SendClicked" prefHeight="58.0" prefWidth="142.0" text="Send to Tab2 & Tab3" />
</children>
</AnchorPane>
Tab2.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="206.0" prefWidth="226.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.tab.Tab2Controller">
<children>
<Label fx:id="lbl2" alignment="CENTER" layoutX="37.0" layoutY="46.0" prefHeight="17.0" prefWidth="152.0" text="Default Tab2 text" />
</children>
</AnchorPane>
Tab3.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="206.0" prefWidth="226.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.tab.Tab3Controller">
<children>
<Label fx:id="lbl3" alignment="CENTER" layoutX="37.0" layoutY="46.0" prefHeight="17.0" prefWidth="152.0" text="Default Tab3 text" />
</children>
</AnchorPane>
Here is a example
fxml
create 3 panes, with its own button and label
<?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="380.0" prefWidth="387.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ask.FXMLDocumentController">
<children>
<Pane fx:id="p3" prefHeight="380.0" prefWidth="387.0" visible="false">
<children>
<Label layoutX="184.0" layoutY="181.0" text="p3" />
<Button fx:id="p3previous" layoutX="152.0" layoutY="225.0" mnemonicParsing="false" text="previous" />
</children>
</Pane>
<Pane fx:id="p2" prefHeight="380.0" prefWidth="387.0" visible="false">
<children>
<Label layoutX="184.0" layoutY="181.0" text="p2" />
<Button fx:id="p2previous" layoutX="78.0" layoutY="255.0" mnemonicParsing="false" text="previous" />
<Button fx:id="p2next" layoutX="239.0" layoutY="255.0" mnemonicParsing="false" text="next" />
</children>
</Pane>
<Pane fx:id="p1" prefHeight="380.0" prefWidth="387.0">
<children>
<Button fx:id="p1next" layoutX="167.0" layoutY="210.0" mnemonicParsing="false" text="next" />
<Label layoutX="184.0" layoutY="181.0" text="p1" />
</children>
</Pane>
</children>
</AnchorPane>
controller
add button action event, use setVisible(boolean) to control which pane should show.
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
public class FXMLDocumentController implements Initializable {
#FXML Pane p1;
#FXML Pane p2;
#FXML Pane p3;
#FXML Button p1next;
#FXML Button p2next;
#FXML Button p2previous;
#FXML Button p3previous;
public void initialize(URL url, ResourceBundle rb)
{
p1next.setOnAction(e->{ p1.setVisible(false); p2.setVisible(true); });
p2next.setOnAction(e->{ p2.setVisible(false); p3.setVisible(true); });
p2previous.setOnAction(e->{ p2.setVisible(false); p1.setVisible(true); });
p3previous.setOnAction(e->{ p3.setVisible(false); p2.setVisible(true); });
}
}
You do not need to add all the content you create in a fxml file to the scene. the <fx:define> tag can be used to create Node that are not part of the object scene (yet). Use a suitable Parent that allows you to proper display the content.
Example:
<StackPane fx:id="container" prefHeight="432.0" prefWidth="443.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.MainController">
<children>
<fx:include fx:id="tab1" source="tab/Tab1.fxml" />
<fx:define>
<fx:include fx:id="tab2" source="tab/Tab2.fxml" />
<fx:include fx:id="tab3" source="tab/Tab3.fxml" />
</fx:define>
</children>
</StackPane>
public class MainController {
#FXML private Tab1Controller tab1Controller;
#FXML private Tab2Controller tab2Controller;
#FXML private Tab3Controller tab3Controller;
#FXML private Node tab1;
#FXML private Node tab2;
#FXML private Node tab3;
#FXML private StackPane container;
public void initialize() {
tab1Controller.init(this);
tab2Controller.init(this);
tab3Controller.init(this);
}
public void setTab2LabelText(String text) {
tab3Controller.lbl3.setText(text);
tab2Controller.lbl2.setText(text);
}
public void toTab2() {
container.getChildren().setAll(tab2);
}
}
I'm developing a password manager program. When opening a new window in this program it throws an exception on the addEntry() mouse click event. I have a Main class that opens the main window (with sample.fxml) and a Controller class that manages to open the new window (with addNewEntryDialog.fxml). Here's my code:
Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.io.IOException;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("/sample.fxml"));
primaryStage.setTitle("Password Manager");
primaryStage.setScene(new Scene(root, 800, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Controller.java
package sample;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.ResourceBundle;
public class Controller implements Initializable {
public ObservableList<Data> data;
public TableView dbTable;
public TableColumn siteColumn, usernameColumn, passwordColumn;
public ToggleButton showPasswordToggle;
#Override
public void initialize(URL location, ResourceBundle resources) {
fillTable();
}
public void fillTable(){
data = FXCollections.observableArrayList();
String query = "SELECT * FROM accounts";
try {
Connection connection = connectToDatabase();
ResultSet resultSet = connection.createStatement().executeQuery(query);
while (resultSet.next()) {
data.add(new Data(resultSet.getString(1), resultSet.getString(2), resultSet.getString(3)));
}
siteColumn.setCellValueFactory(new PropertyValueFactory("site"));
usernameColumn.setCellValueFactory(new PropertyValueFactory("username"));
passwordColumn.setCellValueFactory(new PropertyValueFactory("password"));
dbTable.setItems(data);
} catch (SQLException e) {
e.printStackTrace();
}
}
#FXML
public void addEntry() throws IOException {
Stage stage = new Stage();
Parent root = FXMLLoader.load(getClass().getResource("/addEntryDialog.fxml"));
stage.setTitle("Add new entry");
stage.setScene(new Scene(root, 800, 600));
stage.show();
}
addEntryDialog.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<GridPane layoutX="28.0" layoutY="21.0" prefHeight="123.0" prefWidth="317.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label layoutX="33.0" layoutY="26.0" text="Site:" />
<Label layoutX="28.0" layoutY="78.0" text="Username:" GridPane.rowIndex="1" />
<Label layoutX="44.0" layoutY="135.0" text="Password:" GridPane.rowIndex="2" />
<TextField fx:id="siteField" layoutX="150.0" layoutY="21.0" GridPane.columnIndex="1" />
<TextField fx:id="usernameField" layoutX="150.0" layoutY="73.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<PasswordField fx:id="passwordField" layoutX="150.0" layoutY="123.0" GridPane.columnIndex="1" GridPane.rowIndex="2" />
</children>
</GridPane>
<Button layoutX="327.0" layoutY="163.0" mnemonicParsing="false" text="OK" />
<Button layoutX="246.0" layoutY="163.0" mnemonicParsing="false" text="Cancel" />
</children>
</Pane>
sample.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<Pane prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<TableView fx:id="dbTable" layoutX="4.0" layoutY="85.0" prefHeight="505.0" prefWidth="790.0">
<columns>
<TableColumn fx:id="siteColumn" prefWidth="263.0" text="Site" />
<TableColumn fx:id="usernameColumn" prefWidth="263.0" text="Username" />
<TableColumn fx:id="passwordColumn" prefWidth="263.0" text="Password" />
</columns>
</TableView>
<GridPane layoutX="14.0" layoutY="27.0" prefHeight="25.0" prefWidth="263.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Button fx:id="addNewEntry" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" onMouseClicked="#addEntry" text="Add.." GridPane.columnIndex="0" />
<Button fx:id="removeEntry" layoutX="83.0" layoutY="14.0" mnemonicParsing="false" text="Remove.." GridPane.columnIndex="1" />
<Button fx:id="editEntry" layoutX="178.0" layoutY="14.0" mnemonicParsing="false" text="Edit.." GridPane.columnIndex="2" />
</children>
</GridPane>
<ToggleButton fx:id="showPasswordToggle" layoutX="671.0" layoutY="27.0" mnemonicParsing="false" text="Show Password" />
</children>
</Pane>
STACK TRACE
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
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.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$ClickGenerator.postProcess(Scene.java:3470)
at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3766)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
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$354(GlassViewEventHandler.java:388)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
... 31 more
Caused by: javafx.fxml.LoadException:
/home/umberto/passwordManager/out/production/passwordManager/addEntryDialog.fxml
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
at sample.Controller.addEntry(Controller.java:58)
... 41 more
Caused by: java.lang.NullPointerException
at sample.Controller.loadTableData(Controller.java:45)
at sample.Controller.initialize(Controller.java:30)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
... 49 more
Look at your addEntryDialog.fxml file. There is definition of this view's controller:
<Pane ... fx:controller="sample.Controller>
JavaFX loads the view, looks for the controller and creates it. (At this moment another sample.Controller object is instantiated). After creating it sees that this controller implements Initializable interface, so it executes initialize method which in turn calls fillTable method and finally the statement siteColumn.setCellValueFactory(..) is reached. The problem is that there's no siteColumn for addEntryDialog.fxml view - it has not been binded since there's no element on view with that id.
Solution is to create proper controller for addEntryView.fxml and call it in xml fx:controller attribute.