Internal NPE when launching JavaFX Application - java

So basically I began a dummy JavaFX project just to achieve a minimalistic example for my actual problem. But now I am not even able to run that minimalistic project anymore and do not receive enough error information to actually google it myself out. So right now, when I run the code, I receive the given error stack, which does not lead me anywhere.
I am using IntelliJ. JavaFX libraries are set correctly and VM Options set to:
--module-path "C:\Program Files\Java\javafx-sdk-11.0.2\lib" --add-modules javafx.controls,javafx.fxml
On top, when I run the code, those errors pop up in console, but the application seems to still be running, because I need to press the Red Stop Button of IntelliJ to actually stop it.
Has anyone some guess, what goes wrong here? I am not experienced enough to follow those errors, since they do not point into my code, but rather into some Deep Java code.
The Exception:
Exception in thread "main" 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:566)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.NullPointerException
at java.base/java.lang.reflect.Method.invoke(Method.java:559)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
... 5 more
Main.java:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.io.IOException;
public class Main extends Application {
private Stage rootStage;
public BorderPane mainWindow;
public AnchorPane left;
public AnchorPane bottom;
#Override
public void start(Stage primaryStage) throws Exception {
this.rootStage = primaryStage;
loadMainWindow();
}
public void loadMainWindow() throws IOException {
FXMLLoader loaderMainWindow = new FXMLLoader(Main.class.getResource("MainWindow.fxml"));
mainWindow = loaderMainWindow.load();
FXMLLoader loaderLeft = new FXMLLoader(Main.class.getResource("Left.fxml"));
left = loaderLeft.load();
mainWindow.setLeft(left);
//mainWindow.setBottom(bottom);
Scene scene = new Scene(mainWindow);
rootStage.setScene(scene);
rootStage.show();
}
public void main(String[] args) {
launch(args);
}
}
MainWindow.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.MainWindowController" />
MainWindowController:
package sample;
import javafx.fxml.Initializable;
import java.net.URL;
import java.util.ResourceBundle;
public class MainWindowController implements Initializable {
private Main main;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
public void setMain(Main main) {
this.main = main;
}
}
Left.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="400.0" prefWidth="100.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.LeftController">
<children>
<Button fx:id="button" layoutX="237.0" layoutY="169.0" mnemonicParsing="false" onAction="#buttonClick" text="Button" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" />
</children>
</AnchorPane>
LeftController.java:
package sample;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import java.awt.event.ActionEvent;
import java.net.URL;
import java.util.ResourceBundle;
public class LeftController implements Initializable {
#FXML
private Button button;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
public void buttonClick(javafx.event.ActionEvent actionEvent) {
System.out.println("Some Stuff");
}
}

Solution
The error you're getting is caused by your main(String[]) method not being static. If you make it static then the error will go away.
Some Explanation
JavaFX offers the ability to launch applications without providing a main method, so long as the main class is a subclass of Application. However, developers can still include a main method which means this special launch functionality has to handle that situation gracefully. In other words, an explicit main method present in the Application subclass must act like the entry point of the application from the developer's point of view. Nonetheless, behind the scenes some deep internal class has become the "real" main class.
To do this, the main method is located—if present at all—via Class#getMethod(String,Class...) which, while only returning public methods, doesn't distinguish between static and non-static methods. If found, Method#invoke(Object,Object...) is used to invoke the main method reflectively. The first argument of invoke is the instance that the method should be invoked on; in the case of static methods the value is null. Unfortunately, the code assumes the method it found is static which causes a NullPointerException to be thrown—you can't call an instance method on a null "instance".
Update: This issue has been submitted on GitHub (#570) and subsequently JBS (JDK-8230119). The current idea is to emit a warning rather than throw the NullPointerException. However, the functionality that allows launching without a main method may be deprecated in a future release, which will affect how this issue is addressed.

Related

fx:include with "resources" throws MissingResourceException but works in Java Code

I'm trying to use the resource tag inside fx:include in a FXML file.
What I don't understand is, that loading the resource bundle manually with ResourceBundle.getBundle() works completely fine.
I already tried a lot of variants in the fxml like:
"lang_challenges"
"wand555/github/io/challengesreworkedgui/lang_challenges"
package wand555.github.io.challengesreworkedgui;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Set;
public class ChallengeApplication extends Application {
#Override
public void start(Stage stage) throws IOException {
ResourceBundle.clearCache();
ResourceBundle bundle = new ResourceBundleWrapper(ResourceBundle.getBundle("wand555/github/io/challengesreworkedgui/lang_challenges"));
System.out.println(bundle.getString("challenge.name")); // outputs "abc"
FXMLLoader loader = new FXMLLoader(ChallengeApplication.class.getResource("overview.fxml"), bundle);
Parent root = loader.load();
Scene scene = new Scene(root, 1000, 1000);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
// this class effectively does nothing, but it will be loaded by the
// application class loader
// instead of the system class loader.
private static class ResourceBundleWrapper extends ResourceBundle {
private final ResourceBundle bundle;
ResourceBundleWrapper(ResourceBundle bundle) {
this.bundle = bundle;
}
#Override
protected Object handleGetObject(String key) {
return bundle.getObject(key);
}
#Override
public Enumeration<String> getKeys() {
return bundle.getKeys();
}
#Override
public boolean containsKey(String key) {
return bundle.containsKey(key);
}
#Override
public Locale getLocale() {
return bundle.getLocale();
}
#Override
public Set<String> keySet() {
return bundle.keySet();
}
}
}
overview.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<AnchorPane prefHeight="500.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wand555.github.io.challengesreworkedgui.controllers.OverviewController">
<children>
<VBox>
<children>
<StackPane alignment="CENTER_LEFT">
<children>
<Button fx:id="exportButton" mnemonicParsing="false" onAction="#onExport" text="Export" />
</children>
</StackPane>
<HBox prefHeight="100.0" prefWidth="200.0" spacing="25.0">
<children>
<fx:include fx:id="challengesOverview" source="challenges/challenges_overview.fxml" resources="lang_challenges" charset="utf-8"/>
<Separator orientation="VERTICAL" prefHeight="200.0" />
<fx:include source="goals/goal_overview.fxml" />
<Separator orientation="VERTICAL" prefHeight="200.0" />
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>
The lang_challenges.properties contains a single key-value pair
challenge.name=abc
The `lang_challenges_de.properties' has the same content
challenge.name=abc
And this is the error message I'm getting
Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at javafx.graphics#19/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:465)
at javafx.graphics#19/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:364)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1082)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics#19/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:901)
at javafx.graphics#19/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: javafx.fxml.LoadException:
/Users/felixnaumann/Documents/ChallengesReworked/ChallengesReworkedGUI/target/classes/wand555/github/io/challengesreworkedgui/overview.fxml:21
at javafx.fxml#19/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2707)
at javafx.fxml#19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2685)
at javafx.fxml#19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
at javafx.fxml#19/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2516)
at challenges.reworked.gui/wand555.github.io.challengesreworkedgui.ChallengeApplication.start(ChallengeApplication.java:22)
at javafx.graphics#19/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:847)
at javafx.graphics#19/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
at javafx.graphics#19/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics#19/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
at javafx.graphics#19/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
Caused by: java.util.MissingResourceException: Can't find bundle for base name lang_challenges, locale de_DE
at java.base/java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:2045)
at java.base/java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1683)
at java.base/java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1575)
at java.base/java.util.ResourceBundle.getBundle(ResourceBundle.java:1280)
at javafx.fxml#19/javafx.fxml.FXMLLoader$IncludeElement.processAttribute(FXMLLoader.java:1100)
at javafx.fxml#19/javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:230)
at javafx.fxml#19/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:755)
at javafx.fxml#19/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2808)
at javafx.fxml#19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2634)
... 9 more
Exception running application wand555.github.io.challengesreworkedgui.ChallengeApplication
Whew, finally figured it out after digging deep into the source code of ResourceBundle and ClassLoader.
How to fix it:
Really easy way:
Put your .properties files at the root of the resources folder. Then use it inside fxml
<fx:include source="second.fxml" resources="second_bundle"/>
and then everything should work fine.
However this approach is not suitable for larger projects which subdivide the resource bundles into different packages.
Using sub-packages in resources package
Give the fully qualified path name in the resources tag.
So for example if your package structure from src is com/example/demo/ (also in the resources folder) then use
<fx:include source="second.fxml" resources="com/example/demo/second_bundle"/>
But we are not done yet. You need to open the package to all modules in the module-info.java, explicitly using
opens com.example.demo to javafx.fxml;
does not work.
Instead you need to write
opens com.example.demo;
My two cents
Honestly to me this sounds like a bug.
I debugged the entire loading process and when the second_bundle is loaded from inside the fxml file, the caller module is javafx.fxml. And as the java doc for getResourceAsStream (which is internally called when loading) states:
A package name is derived from the resource name. If the package name is a package in the module then the resource can only be located by the caller of this method when the package is open to at least the caller's module. If the resource is not in a package in the module then the resource is not encapsulated.
So in theory opening your package to just javafx.fxml should work, but it doesn't...
Full demo project
This demo project uses sub-packages.
Project structure:
HelloApplication:
public class HelloApplication extends Application {
#Override
public void start(Stage stage) throws IOException {
ResourceBundle bundle = new ResourceBundleWrapper(ResourceBundle.getBundle("test_bundle"));
System.out.println(bundle.getString("first.button")); // outputs "English/Deutsch"
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("first.fxml"), bundle);
Scene scene = new Scene(fxmlLoader.load(), 320, 240);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
// this class effectively does nothing, but it will be loaded by the
// application class loader
// instead of the system class loader.
private static class ResourceBundleWrapper extends ResourceBundle {
private final ResourceBundle bundle;
ResourceBundleWrapper(ResourceBundle bundle) {
this.bundle = bundle;
}
#Override
protected Object handleGetObject(String key) {
return bundle.getObject(key);
}
#Override
public Enumeration<String> getKeys() {
return bundle.getKeys();
}
#Override
public boolean containsKey(String key) {
return bundle.containsKey(key);
}
#Override
public Locale getLocale() {
return bundle.getLocale();
}
#Override
public Set<String> keySet() {
return bundle.keySet();
}
}
}
first.fxml:
<VBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml"
fx:controller="com.example.demo.HelloController">
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/>
</padding>
<Label fx:id="welcomeText"/>
<Button text="%first.button" onAction="#onHelloButtonClick"/>
<fx:include source="second.fxml" resources="com/example/demo/second_bundle"/>
</VBox>
second.fxml:
<VBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml">
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/>
</padding>
<Label fx:id="welcomeText"/>
<Button text="%second.button"/>
</VBox>
test_bundle.properties:
first.button=English
second_bundle.properties:
second.button=Hello
module-info.java:
module com.example.demo {
requires javafx.controls;
requires javafx.fxml;
opens com.example.demo;
exports com.example.demo;
}

Connecting SQL Server with Java (javafx)

I have the setup below for the connection SQL Server with Java. Am also using javafx. I am very new to developing with Java. Note: I added the sqljdbc driver. I don't want to add main to DBConnection because am using the Connection method in the controller. Is there a way to fix this or how can I add main method without changing the connection method? Am getting error message:
Error Message
Error: Main method not found in class application.ConnectionDB, please define the main method as:
public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
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 fx:controller="application.MainController" prefHeight="407.0" prefWidth="578.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label layoutX="123.0" layoutY="65.0" prefHeight="31.0" prefWidth="79.0" text="Date:" />
<Label layoutX="123.0" layoutY="138.0" prefHeight="25.0" prefWidth="127.0" text="Rim Current Value:" />
<Label layoutX="125.0" layoutY="210.0" text="Rim Sales Value for the Month:" />
<Label layoutX="123.0" layoutY="283.0" text="Rim Sold Cost Bought:" />
<TextField fx:id="txtdate" layoutX="123.0" layoutY="97.0" />
<TextField fx:id="txtcurvalue" layoutX="123.0" layoutY="163.0" />
<TextField fx:id="txtsalesvalue" layoutX="123.0" layoutY="234.0" />
<TextField fx:id="txtsoldcost" layoutX="123.0" layoutY="300.0" />
<Button layoutX="246.0" layoutY="340.0" mnemonicParsing="false" onAction="#Rmsubmit" prefHeight="25.0" prefWidth="103.0" text="Submit" />
</children>
</AnchorPane>
Connection Class
package application;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ConnectionDB
{
public static Connection dbConn() {
Connection conn = null;
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String url = "jdbc:sqlserver:[server name];database=SalesManager;user=[username];password=[password];encrypt=true;trustServerCert ificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30";
conn = DriverManager.getConnection(url);
}
catch (ClassNotFoundException | SQLException ex) {
Logger.getLogger(ConnectionDB.class.getName()).log(Level.SEVERE,null,ex);
}
return conn;
}
}
Controller
package application;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ResourceBundle;
import javax.print.DocFlavor.URL;
public class MainController {
#FXML
public TextField txtdate;
#FXML
public TextField txtcurvalue;
#FXML
public TextField txtsalesvalue;
#FXML
public TextField txtsoldcost;
public Connection conn =null;
public PreparedStatement pat = null;
#FXML
public void Rmsubmit(ActionEvent actionEvent) {
String sqla = "Insert into RimCalc(Date, Rim_Vale,Rim_Sales,Rim_Cost) Values (?,?,?,?)";
String date = txtdate.getText();
String rim_value = txtcurvalue.getText();
String Rim_Sales = txtsalesvalue.getText();
String rim_cost = txtsoldcost.getText();
try {
pat = conn.prepareStatement(sqla);
pat.setString(1, date);
pat.setString(2, rim_value);
pat.setString(3, Rim_Sales);
pat.setString(4, rim_cost);
int i = pat.executeUpdate();
if(i==1) {
System.out.println("Insert Successfully");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void initializer(URL url, ResourceBundle rb) {
conn = application.ConnectionDB.dbConn();
}
}
Java programs require a main method as an entry point in order to run. The standard definition of a main method is like this:
public static void main(String[] args) {
// First code of your program goes here
}
This main() method should include the code that starts your application and loads any interface elements for display.
A JavaFX application also needs to have a class that extends Application and override its start() method.
Here is a very quick and dirty example of one such class:
import javafx.application.Application;
import javafx.stage.Stage;
class Main extends Application {
public static void main(String[] args) {
launch(args); // Starts the JavaFX application and calls the start() method
}
#Override
public void start(Stage primaryStage) throws Exception {
// Here is where you'll initialize your views and such
}
}
I would recommend taking a few Java and JavaFX tutorials to get a feel for some of the basics before attempting more complicated tasks like connecting to databases.

resolving onAction='#initialize', either the event handler is not in the Namespace or there is an error in the script

This is my first program in javafx. I have just created a AnchorPane with the help of scene Builder. what I want from this is when we click any where in the AncherPane it should show the coordinate point of that pixel.
This is the controller class
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
public class AxisController implements Initializable{
#FXML
private AnchorPane anchr;
#Override
public void initialize(URL location, ResourceBundle resources) {
assert anchr != null : "fx:id=\"anchr\" was not injected: check your FXML file 'AxisFxml.fxml'.";
anchr.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println(event.getX());
System.out.println(event.getY());
}
});
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="anchr" onMouseClicked="#initialize" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.AxisController">
<!-- TODO Add Nodes -->
</AnchorPane>
Error Message
javafx.fxml.LoadException: Error resolving onAction='#initialize', either the event handler is not in the Namespace or there is an error in the script.
/home/xyz/workspace/AxisExample/bin/application/AxisFxml.fxml:9
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2597)
at javafx.fxml.FXMLLoader.access$100(FXMLLoader.java:103)
at javafx.fxml.FXMLLoader$Element.processEventHandlerAttributes(FXMLLoader.java:610)
at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:770)
at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2823)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2532)
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 application.AxisMain.start(AxisMain.java:16)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
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.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)
You have a couple of misunderstandings here.
The methods whose names you set as values to the "event handler attributes", such as onMouseClicked, are the methods that will be invoked when those events happen. They should just contain the code that you want to be executed when, in this case, the mouse is clicked. You should not register event handlers in these methods. (This would mean: "when the anchor pane is clicked, register an event handler for the anchor pane being clicked", which is clearly not what you intend.)
As a consequence of this, methods that are registered in the FXML as event handler methods should take a single parameter of the correct event type. (It is also allowable to take no parameters, if you don't need the event object - a common scenario.)
The error you are getting is because the method you have declared to be the event handler (initialize(), which has a completely different role), has the wrong signature: it take the wrong number (and type) of parameters.
Secondly, the initialize() method, which may either be declared with no parameters, or be declared with parameters of type URL and ResourceBundle, is invoked during the process of loading the FXML. This happens after all the #FXML-annotated fields have been injected, but before the root of the UI is returned from the call to FXMLLoader.load(). Thus it's safe to access #FXML-annotated fields here: they will have been properly initialized.
So there are two distinct ways of registering event handlers.
Either:
Define a method in the controller, and reference it in the FXML file:
<AnchorPane fx:id="anchr" onMouseClicked="#handleClick" ... fx:controller="application.AxisController">
<!-- TODO Add Nodes -->
</AnchorPane>
and then
public class AxisController implements Initializable{
#FXML
private AnchorPane anchr;
#Override
public void initialize(URL location, ResourceBundle resources) {
assert anchr != null : "fx:id=\"anchr\" was not injected: check your FXML file 'AxisFxml.fxml'.";
}
#FXML
private void handleClick(MouseEvent event) {
System.out.println(event.getX());
System.out.println(event.getY());
}
}
Or:
Remove the onMouseClicked attribute from the FXML file, and register the event handler in the initialize() method. (So the controller is exactly as you have it.)
I would assume that the problem lies in your anchorPane on your FXML, have you assigned a function to the anchorPane for a click event on your FXML? if you have you can set the function for that event by doing the same as if you where initializing the variable for example:
#FXML
private void restartExited() {
exitedTransition(0, "circle", null, buttonCirc);
}
you can tell your anchorPane in the FXML to do this function when it is clicked or mouseOver for example, you do not need to set it in the controller as well as the FXML.
Or in your case:
#FXML
private void initialize() {
anchr.setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println(event.getX());
System.out.println(event.getY());
}
});
}
Or you could remove the reference to onClick on the AnchorPane in your FXML and use your current code.
EDIT
Can I ask where you are defining the stage and the FXML to load to the stage, is this your stage initializer for your application or the controller for the FXML?

TreeTableColumn.visible : A bound value cannot be set

I make a simple JavaFX application. In this application there is a treetable with 2 columns and a check box. If check box is selected column 2 will be visible, otherwise not visible. To do this I bound tree table column visible property to checkbox selected property. When I click the check box column state change but at the same time gives.
Caused by: java.lang.RuntimeException: TreeTableColumn.visible : A
bound value cannot be set.
If I use bidirectional binding I don't get this error. But I don't need bidirectional binding. Is it a bug or I don't use bind correctly? Please use below code to reproduce this error. I use jdk1.8.0_111.
JavaFXApplication.java
package test;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class JavaFXApplication extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
FXMLDocumentController.java
package test;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
public class FXMLDocumentController implements Initializable {
#FXML
private TreeTableView<?> table;
#FXML
private CheckBox box;
#FXML
private TreeTableColumn<?, ?> c2;
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
c2.visibleProperty().bind(box.selectedProperty());
}
}
FXMLDocument.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.TreeTableColumn?>
<?import javafx.scene.control.TreeTableView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="390.0" prefWidth="452.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.65" fx:controller="javafxapplication2.FXMLDocumentController">
<children>
<TreeTableView fx:id="table" layoutX="2.0" prefHeight="390.0" prefWidth="149.0">
<columns>
<TreeTableColumn prefWidth="75.0" text="C1" />
<TreeTableColumn fx:id="c2" prefWidth="75.0" text="C2" visible="false" />
</columns>
</TreeTableView>
<CheckBox fx:id="box" layoutX="234.0" layoutY="77.0" mnemonicParsing="false" text="CheckBox" />
</children>
</AnchorPane>
I think this actually is not a bug. It's definitely mysterious and unexpected behavior though. Part of the problem is that the binding conflict is coming from TableHeaderRow, which is created by the skin at display time.
The TableHeaderRow is responsible for rendering all the column headers, and it includes this built-in button for a menu that, by default, is a radio selection list of columns to show/hide:
As a result, the TableHeaderRow creates a bidirectional binding between these menu entries' selection state and each column's visible property.
It actually is possible to undo this binding but I found it annoying since the TableHeaderRow is null until the TableView is displayed. But, adapting this solution to access the TableHeaderRow, we can do something like:
TableHeaderRow headerRow = ((TableViewSkinBase) tableView.getSkin()).getTableHeaderRow();
try {
// get columnPopupMenu field
Field privateContextMenuField = TableHeaderRow.class.getDeclaredField("columnPopupMenu");
// make field public
privateContextMenuField.setAccessible(true);
// get context menu
ContextMenu contextMenu = (ContextMenu) privateContextMenuField.get(headerRow);
for (MenuItem menuItem : contextMenu.getItems()) {
// Assuming these will be CheckMenuItems in the default implementation
BooleanProperty selectedProperty = ((CheckMenuItem) menuItem).selectedProperty();
// In theory these menu items are in parallel with the columns, but I just brute forced it to test
for (TableColumn<?, ?> tableColumn : tableView.getColumns()) {
// Unlink the column's visibility with the menu item
tableColumn.visibleProperty().unbindBidirectional(selectedProperty);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
// Not strictly necessary but we don't want to be misleading :-p
tableView.setTableMenuButtonVisible(false);
But here's the kicker: you have to do this every time a column's visibility changes, because the TableHeaderRow has a listener that rebuilds the menu, and re-links the properties, every time a column is shown.
You could, of course, find a way to disable that listener.. but clearly this is already ridiculous and probably unnecessary.
Anyway, as you noted:
If I use bidirectional binding I don't get this error. But I don't need bidirectional binding.
I think the second statement isn't technically true: your use case doesn't require bidirectional binding, but it is actually appropriate here since there are other properties already linked with a column's visibility.
So, I would use bidirectional binding.

Inconsistent Error - java.lang.reflect.InvocationTargetException

This is probably a simple error, but I can't figure it out. I can call getText on TextArea controls just fine, but TextField controls are constantly thowing an InvocationTargetException error. They are both defined in the same way and I've triple checked the FX IDs and controller is correct. Not sure what else could cause this. Please help!
Relevant FXML - Root Node
<VBox prefHeight="500.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="api.LayoutController">
Field FXML
<TextField fx:id="apitoken" text="mytopsecrettoken" GridPane.columnIndex="1">
<GridPane.margin><Insets /></GridPane.margin></TextField>
Controller:
public class LayoutController implements Initializable {
#FXML
private TextArea result,data;
private TextField apitoken,object;
#FXML
private void submit(ActionEvent event) {
result.setText(apitoken.getText());
}
Exception information:
Executing C:\Users\XXX\Documents\NetBeansProjects\API\dist\run1375954609\API.jar using platform C:\Program Files\Java\jdk1.8.0_05\jre/bin/java
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1768)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1651)

Categories

Resources