I want to create new label in another fxml when a button is clicked. I used the following code but the following exception is thrown
java.lang.RuntimeException:
java.lang.reflect.InvocationTargetException
The code:
Controller.java
public class Controller {
public AnchorPane anchorPane;
public void OpenSecond() throws Exception{
Stage primaryStage = new Stage();
Parent root = FXMLLoader.load(getClass().getResource("sample1.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public void AddLabe(){
Label label = new Label("Label");
anchorPane.getChildren().add(label);
}
}
second.java
public class Second {
public void AddLiabel()
{
Controller controller = new Controller();
controller.AddLabe();
}
}
I am using IntelliJ IDEA and Scene builder
You should be getting this exception because Java couldn't find the specified file or it is empty. Search for
Caused by: javafx.fxml.LoadException:
in the exception.
Adding the "sample1.fxml" and initializing it with a pane should fix the problem.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.Pane?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="275.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" />
Most probably you miss annotation for anchorPane and JavaFX didn't initialize it. Try next:
#FXML
public AnchorPane anchorPane;
and make sure anchorPane is listed in your FXML file.
Related
I am attempting to create a method in my main screen controller to set a new scene in my program. When attempting to do so, I get the following error:
Error resolving onAction='#partAddButtonPushed', either the event handler is not in the Namespace or there is an error in the script.
The relevant fxml code is:
<AnchorPane id="AnchorPane" prefHeight="420.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="john.Doe.View_Controller.MainController">
<children>
<Button id="addPartsButton" fx:id="partAdd" layoutX="190.0" layoutY="340.0" maxWidth="70.0" minWidth="70.0" mnemonicParsing="false" onAction="#partAddButtonPushed" prefWidth="70.0" text="Add">
and the relevant code in the controller is:
public class MainController implements Initializable {
#FXML
private Button partAdd;
#FXML
private void partAddButtonPushed(ActionEvent event) throws IOException {
Parent partAddParent = FXMLLoader.load(getClass().getResource("/View/AddPart.fxml"));
Scene AddPartScene = new Scene (partAddParent);
Stage window = (Stage)((Node)event.getSource()).getScene().getWindow();
window.setScene(AddPartScene);
window.show();
}
Would anyone happen to know why they are not linking up?
So I'm trying to move from Swing to JavaFX and I just declare the start() and launch() methods without knowing how they work. But below code prints false and false to the console. However when I click the button in the GUI, built with Scene Builder, that executes myMethod(), this time it prints true. Why does it say that primaryStage isn't instantiated?
addition information:
I also made this class my Controller, for the same reason - it needs access to the Stage reference. The full version of Main, which I didn't post, implements Initializable if that matters.
As a bonus question I was wondering if I need the field of primaryStage to reference the Application Stage, which there would only be one of?, in myMethod().
public class Main extends Application {
private Stage primaryStage;
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
try {
Scene scene = new Scene(FXMLLoader.load(getClass().getResource("Sample.fxml")),600,400);
primaryStage.setScene(scene);
} catch(Exception e) {
e.printStackTrace();
}
primaryStage.show();
//both lines below print false; As they should.
System.out.println(this.primaryStage == null);
myMethod();
}
public static void main(String[] args) {
launch(args);
}
public void myMethod() {
System.out.println(primaryStage == null);
}
}
EDIT
placing this FXML document in the same folder as above class will let you run Main to see that the button does indeed print true.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<HBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Main">
<children>
<Button mnemonicParsing="false" onAction="#myMethod" text="Button" />
</children>
</HBox>
That is because the FXMLLoader will create new instance of application.Main class, in where the start() method is not invoked and thus private Stage primaryStage is null.
It is better to separate the main class and the controller for the FXML, and pass the primary stage later if it is necessary:
...
try
{
FXMLLoader loader = new FXMLLoader( getClass().getResource( "Sample.fxml" ) );
Scene scene = new Scene( loader.load(), 600, 400 );
( (MyController) loader.getController() ).setPrimaryStage(primaryStage);
primaryStage.setScene( scene );
}
catch ( Exception e )
{
e.printStackTrace();
}
...
where the MyController class can be as simple as:
public class MyController {
private Stage primaryStage;
public void setPrimaryStage(Stage primaryStage) {
this.primaryStage = primaryStage;
}
}
but also can implement Initializable interface. Refer to Introduction to FXML :: Controllers.
Also note that you can get the scene and its stage from any node that is part of that constructed scene graph (i.e. a stage that is shown) by:
Scene scene = anynode.getScene();
Stage primaryStage = (Stage) anynode.getScene().getWindow();
Of course, for the secondary stages created by you the getWindow() will return that stage and not the primary stage.
There is no need at all to jump through any of these hoops to get access to the window. You can just call getScene().getWindow() on any node to get the window in which it is displayed (and of course you can just inject any node into your controller in the usual way).
Don't use the Application subclass as the controller class: you will have (at least) two different instances (one created by the launch() method, because it's the Application subclass, and one created by the FXMLLoader, because it's the controller class). Different fields will be initialized in the different instances.
Create a controller class, and inject at least one node into it:
public class Controller {
#FXML
private Parent root ;
#FXML
private void myMethod() {
Window window = root.getScene().getStage();
// assuming you are running as a standalone application, the window
// will actually be a Stage instance.
window.hide(); // for example...
}
}
Use this as your controller class and inject the node into it:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<HBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller" fx:id="root">
<children>
<Button mnemonicParsing="false" onAction="#myMethod" text="Button" />
</children>
</HBox>
Preface: I am pretty new to JavaFX
Made an simple image resizing application and need to build an artifact of the application.
Using IntelliJ and Eclipse (tried both), i built normal JAR artifacts and JavaFX artifacts. Both are executable, but only show an empty window.
When starting the application out of the IDE, there is no problem; the window containing all subpanes get displayed as they should.
Any ideas how to solve this problem? Thanks in advance!
Attached code of the application initialization part and a picture of the resulting windows - maybe it helps.
public class MainApp extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
private SettingsViewController settingController;
private MainViewController mainViewController;
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("SimpleImageResizer");
this.primaryStage.getIcons().add(new Image("file:icon.png"));
this.primaryStage.setOnCloseRequest(we -> ConfigurationCache.getInstance().pushConfig());
targetResolutions.addAll(Arrays.asList(ResolutionPreset.values()));
supportedFileFormats.addAll(Arrays.asList(SupportedFileFormat.values()));
initRootLayout();
showMainView();
showSettingsView();
primaryStage.setResizable(false);
}
public void initRootLayout() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));
rootLayout = loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
.
.
.
public static void main(String[] args) {
launch(args);
}
You didn't provide enough information to solve your problem, so here's an example that does work:
Create a package application and put this class into it:
application/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) {
try {
Parent root = FXMLLoader.load(getClass().getResource("/application/RootLayout.fxml"));
Scene scene = new Scene(root,400,400);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Create a "RootLayout.fxml" in the package application.
application/RootLayout.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 xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<children>
<Pane layoutX="-125.0" layoutY="-143.0" prefHeight="200.0" prefWidth="200.0">
<children>
<Button layoutX="134.0" layoutY="161.0" mnemonicParsing="false" text="Button" />
</children>
</Pane>
</children>
</AnchorPane>
In Eclipse select
Export -> Runnable JAR file -> Extract required libraries into
generated JAR
(of course you need to specify the proper launch configuration)
The generated JAR can be executed and has the nodes from the fxml.
loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));
try with
loader.setLocation(MainApp.class.getResource("/view/RootLayout.fxml"));
NetBeans the first variant will not compile in IDE
I faced the similar issue.It works well with the IDE but when I create a jar and try to run it was not able to load the fxml files. Following worked me.You can try and check if its getting the fxml files.
String fxml = "/com/test/fxmls/gui.fxml";
InputStream in = MycLass.class.getResourceAsStream(fxml);
if(in!=null){
FXMLLoader loader = new FXMLLoader();
loader.setBuilderFactory(new JavaFXBuilderFactory());
loader.setLocation(MycLass.class.getResource(fxml));
BorderPane rootLayout = (BorderPane)loader.load(in);
}else{
//log or output the error
}
I think Resource files cannot be accessed from the jar file. So in this case your trying to load the fxml files from the jar which is not possible. other wise follow the method that #Roland has suggested.
I have a small code of javaFX.
I want to draw in canvas but I have some problem of beginner I really don't understand well javaFX.
This is my Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
Controller controller;
#Override
public void start(Stage primaryStage) throws Exception{
controller= new Controller();
controller.Pane = FXMLLoader.load(getClass().getResource("sample.fxml"));
System.out.printf("kk"+controller.canvas.isResizable());
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(controller.Pane, controller.Pane.getPrefWidth(), controller.Pane.getPrefHeight()));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
this is sample.FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.canvas.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="Pane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="284.0" prefWidth="484.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<Canvas fx:id="canvas" height="267.0" layoutX="13.0" layoutY="9.0" width="459.0" AnchorPane.bottomAnchor="8.0" AnchorPane.leftAnchor="13.0" AnchorPane.rightAnchor="12.0" AnchorPane.topAnchor="9.0" />
</children>
</AnchorPane>
For the controller.java there is only canvas and pane declaration.
My question :
Pane is the parent and canvas is the children after doing FXMLloader.load etc, pane is not null but the children are null in the method start (outside like an event of button the children aren't null) why is children null?
To make the canvas resizable there is no method to do such thing, the only solution is to extends from Canvas and #Override method isResizable make it true. But Canvas I get it from FXML if I do
Canvas MyCanvas= new CanvasResizable();
this dosen't work I don't know why.
is there a way like android to make for example canvas=(Canvas) findbyid(FXML.id.canvas); (something similar)
and my last question how can we change the color of canvas there is no method to do that.
I'm sorry if my question is already asked by a diffirent why, I searched so much in google there is a lack of documentation of javaFX.
FXML controller should not be created directly. It will be initialized for you by FXMLLoader:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Pane root = loader.load(); // controller was initialized
controller = loader.getController();
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, root.getPrefWidth(), root.getPrefHeight()));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
You can find more details in Oracle tutorials: http://docs.oracle.com/javafx/2/fxml_get_started/fxml_tutorial_intermediate.htm#CACFEHBI
I have a JavaFX Application. I have a button that when clicked calls an action and loads another fxml file. This works perfectly.
I decided to place this functionality from within the menu of the application.
So, I created a Menu and I added Menu Items from within the Scene builder. I properly assign the 'On Action' event, the same way I did with my other button. However I get the following error when I click:
Glass detected outstanding Java exception at -[GlassViewDelegate sendJavaMouseEvent:]:src/com/sun/mat/ui/GlassViewDelegate.m:541
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
Caused by: java.lang.ClassCastException: javafx.scene.control.MenuItem cannot be cast to javafx.scene.Node
at plataformavalidezpredictiva.MainController.handleAction(MainController.java:60)
... 38 more
This is the code for the handler. Once again, this works for a button I placed within the UI and doesn't work from the menu bar:
public void handleAction(ActionEvent event) throws Exception{
Node node = (Node)event.getSource();
Stage stage=(Stage) node.getScene().getWindow();
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("fxml/GUIFile.fxml"));
Parent root = (Parent)fxmlLoader.load();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
The line that seems to give me the problem is:
Node node = (Node)event.getSource();
Any ideas?
Edit: I saw the post here Unable to get Scene from MenuItem in JavaFX but that didn't work for me, because it didn't find the getScene() method for the menu bar.
Inject some node (e.g. the MenuBar, but it really can be any node in the same scene) into the controller. Call getScene() on that node and getWindow() on the Scene.
E.g.
Main.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuItem?>
<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="exitfrommenu.MainController">
<top>
<MenuBar fx:id="menuBar">
<Menu text="File">
<MenuItem text="Exit" onAction="#exit"/>
</Menu>
</MenuBar>
</top>
</BorderPane>
MainController.java
package exitfrommenu;
import javafx.fxml.FXML;
import javafx.scene.control.MenuBar;
public class MainController {
#FXML
private MenuBar menuBar ;
#FXML
private void exit() {
Stage stage = (Stage) menuBar.getScene().getWindow() ;
// This exits the application, but of course you can do anything
// you like with the stage, such as showing a new scene in it:
stage.hide();
}
}
Main.java
package exitfrommenu;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("Main.fxml"));
Scene scene = new Scene(root,400,400);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}