JavaFX Accelerator execute twice - javafx

I'm using Accelerator in my application, and when I hit the F1 key it should open a dialog just once, but when I close the dialog it appears again. The runnable is been called twice.
Does anyone know what it could be? Is it a bug? I'm using a Macbook to develop.
This is my controller:
public class Screen1Controller {
#FXML
private TextField txtCode;
#FXML
private TableView tblProducts;
#FXML
private Button buttonAskUserDecision;
#FXML
public void initialize () {
Platform.runLater(new Runnable() {
#Override
public void run() {
initializeKeyCombinations();
}
});
}
#FXML
private void executePrint (ActionEvent event) {
System.out.println("ExecutePrint");
}
public void initializeKeyCombinations() {
buttonAskUserDecision.getScene().getAccelerators().clear();
buttonAskUserDecision.getScene().getAccelerators().put(
new KeyCodeCombination(KeyCode.F1),
new Runnable() {
#Override
public void run() {
System.out.println("Executed F1");
}
}
);
}
}
This is my FXML:
<StackPane prefHeight="600.0" prefWidth="800.0" stylesheets="#../../../css/main.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Screen1Controller">
<children>
<BorderPane prefHeight="200.0" prefWidth="200.0">
<center>
<ScrollPane fitToHeight="true" fitToWidth="true" BorderPane.alignment="CENTER">
<content>
<VBox alignment="TOP_CENTER">
<children>
<GridPane hgap="10.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="20.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="20.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="30.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="30.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints fillHeight="false" minHeight="30.0" vgrow="NEVER" />
</rowConstraints>
<children>
<TextField fx:id="txtCode" GridPane.columnSpan="2" />
</children>
<VBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</VBox.margin>
</GridPane>
<TableView fx:id="tblProducts" prefHeight="200.0" prefWidth="200.0">
<columns>
<TableColumn prefWidth="75.0" text="C1" />
<TableColumn prefWidth="75.0" text="C2" />
</columns>
</TableView>
</children>
</VBox>
</content>
</ScrollPane>
</center>
<bottom>
<ToolBar maxHeight="80.0" minHeight="80.0" prefHeight="80.0" styleClass="default-skin-pdv-toolbar" stylesheets="#../../../css/main.css">
<items>
<Button fx:id="buttonAskUserDecision" layoutX="10.0" layoutY="20.0" mnemonicParsing="false" onAction="#executePrint" prefHeight="60.0" prefWidth="69.0" styleClass="default-skin-pdv-button">
</Button>
</items>
<padding>
<Insets left="10.0" />
</padding>
</ToolBar>
</bottom>
</BorderPane>
</children>
Inside this screen I have a textfield, a tableview and a toolbar with a button.
I did some new tests. Every time I give focus on my tableview and hit the F1 button, the execution is incremented by 1. For instance, if I click on the tableview and hit F1, it prints "Executed F1" just once on the console and the focus go back to the textfield, if i give focus to the tableview again and hit F1, It prints two times the text on the console and give focus back to the textfield, and if I give focus to the tableview for the third time and press the F1 again it prints three more lines on the console, and so on.
It only happens when I use the F1 button.. When I click the button with the mouse it prints only once.
I removed the TableView from the screen and it stopped duplicating the executions.
The problem is: I need this tableView in my screen. What could be happening here?
That's my Java version details:
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

The problem was in a component (Dialog) from ControlsFX library.
I created a new Project and included a textfield, viewTable and a button. The duplication didn't happened.
When I included the ControlsFX Dialog, the started to happen. When I click the button, with the mouse, the dialog opens just once. But when I use the accelerator to fire the button, the dialog opens twice.
Edited:
I created my own dialog, but it happened again. Instead of using the stage.showAndWait() I tried the stage.show() and it stopped to open twice.
I searched the stackoverflow and found this answer https://stackoverflow.com/a/22463857/916804 ... When I tried to wrap the call to the Dialog with the Platform.runLater the execution happened only once.

Related

Retrieving strings from textfields in a .fxml file when a button is clicked. (creating a login scene to switch scenes to home scene)

very new to programming. I am learning java and javaFX.
I have tried to make a login scene and a home scene and currently have a "login" button that invokes a method in the controller -loginButton()- that switches between the two scenes. The part I am unsure on is how to set up this method to retrieve the strings from the username and password text/password fields.
I am not interested just yet in setting this up with a database. what I want to go for is something like this (rubbish login details for the purpose of example, I would never actually use login info this bad):
public void loginButton(javafx.event.ActionEvent actionEvent) throws IOException {
if(textFromLoginField=="admin"){
if(textFromPasswordField=="Password123"){
//run code to change scene
}
}
}
I know how to switch scene but I dont know how to get the login info (shown as textFromLoginField and textFromPasswordField in the example above.
How I am switching scenes
Node node=(Node) actionEvent.getSource();
Stage stage=(Stage) node.getScene().getWindow();
stage.setScene(new Scene(FXMLLoader.load(getClass().getResource("homeScene.fxml")),750,500));
stage.show();
My FXML text:
VBox maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="159.0" prefWidth="157.0" spacing="10.0" style="-fx-background-color: Black;" HBox.hgrow="NEVER">
<HBox.margin>
<Insets bottom="60.0" top="60.0" />
</HBox.margin>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
<children>
<Label text="LOGIN:" textFill="WHITE" />
<TextField fx:id="loginTextField" promptText="Username" />
<PasswordField fx:id="passwordTextField" promptText="Password" />
<HBox alignment="TOP_RIGHT" prefHeight="21.0" prefWidth="137.0" spacing="10.0">
<children>
<Button mnemonicParsing="false" fx:id="loginbutton" onAction="#loginButton" style="-fx-background-color: Blue;" text="Login" textAlignment="CENTER" textFill="WHITE">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Button>
<Button mnemonicParsing="false" fx:id="helpbutton" onAction="#helpButton" style="-fx-background-color: Orange;" text="Help" textAlignment="CENTER" textFill="WHITE">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Button>
</children>
</HBox>
</children>
</VBox>
Any help greatly appreciated :)
-Also, if I have used any technical vocab incorrectly please let me know. I am new to this. thanks
"==" doesn't work with Strings. Use textFromLoginField.equals();. Check out the string functions.

While making own JOptionPane like class in JavaFX [duplicate]

I get
javafx.fxml.LoadException:
When I'm loading and fxml file using following line of code.
AnchorPane anchorPane = (AnchorPane)loader.load()
This is my fxml file excluding import statements.
<AnchorPane prefHeight="537.0" prefWidth="374.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.buddhikajay.controller.NewTransactionDialogController">
<children>
<GridPane hgap="5.0" layoutX="30.0" layoutY="10.0" prefHeight="544.0" prefWidth="314.0" vgap="5.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="142.0" minWidth="10.0" prefWidth="69.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="226.0" minWidth="10.0" prefWidth="225.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="70.0" minHeight="10.0" prefHeight="33.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="105.0" minHeight="10.0" prefHeight="38.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="156.0" minHeight="10.0" prefHeight="51.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="154.0" minHeight="10.0" prefHeight="43.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="160.0" minHeight="10.0" prefHeight="43.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="161.0" minHeight="10.0" prefHeight="63.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="301.0" minHeight="10.0" prefHeight="180.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="231.0" minHeight="10.0" prefHeight="106.0" vgrow="SOMETIMES" />
</rowConstraints>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
<children>
<Label text="ID" />
<Label text="Date" GridPane.rowIndex="1" />
<Label text="Amont" GridPane.rowIndex="2" />
<Label text="Person" GridPane.rowIndex="4" />
<Label text="Type" GridPane.rowIndex="3" />
<Label text="Resolved" GridPane.rowIndex="5" />
<Label />
<Label text="Description" GridPane.rowIndex="6" />
<TextField fx:id="idTextField" GridPane.columnIndex="1" />
<TextField fx:id="dateTextField" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<TextField fx:id="amountTextField" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<TextArea fx:id="descriptionTextArea" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="225.0" spacing="20.0" GridPane.columnIndex="1" GridPane.rowIndex="7">
<GridPane.margin>
<Insets />
</GridPane.margin>
<padding>
<Insets bottom="10.0" left="20.0" right="10.0" top="10.0" />
</padding>
<children>
<Button fx:id="okButton" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#okActionFired" prefHeight="25.0" prefWidth="75.0" text="Ok" />
<Button fx:id="cancleButton" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#cancleActionFired" prefHeight="25.0" prefWidth="75.0" text="Cancle" />
</children>
</HBox>
<ComboBox fx:id="typeComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<ComboBox fx:id="personComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<ComboBox fx:id="resolvedComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="5" />
</children>
</GridPane>
</children>
</AnchorPane>
The compiler complains that there is an error in line number 1. I'm sure that the path of fxml file is correct. What is wrong with my code?
Here is the full error stack
javafx.fxml.LoadException:
/C:/Users/Buddhika/Documents/Programming/IdeaProjects/VirtualCreditDesktop/out/production/VirtualCreditDesktop/com/buddhikajay/view/NewTransactionDialog.fxml:9
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2595)
at javafx.fxml.FXMLLoader.access$700(FXMLLoader.java:104)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:928)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:967)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:216)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:740)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2701)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2521)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2435)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2403)
at com.buddhikajay.controller.NewTransactionDialogController.showNewTransactionDialog(NewTransactionDialogController.java:68)
at com.buddhikajay.controller.MainApp.start(MainApp.java:51)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$153(LauncherImpl.java:821)
at com.sun.javafx.application.LauncherImpl$$Lambda$50/1976027283.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$166(PlatformImpl.java:323)
at com.sun.javafx.application.PlatformImpl$$Lambda$46/301541210.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$164(PlatformImpl.java:292)
at com.sun.javafx.application.PlatformImpl$$Lambda$48/474926796.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$165(PlatformImpl.java:291)
at com.sun.javafx.application.PlatformImpl$$Lambda$47/1662429848.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$141(WinApplication.java:102)
at com.sun.glass.ui.win.WinApplication$$Lambda$38/519284171.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.InstantiationException: com.buddhikajay.controller.NewTransactionDialogController
at java.lang.Class.newInstance(Class.java:423)
at sun.reflect.misc.ReflectUtil.newInstance(ReflectUtil.java:51)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:923)
... 23 more
Caused by: java.lang.NoSuchMethodException: com.buddhikajay.controller.NewTransactionDialogController.<init>()
at java.lang.Class.getConstructor0(Class.java:3074)
at java.lang.Class.newInstance(Class.java:408)
... 25 more
The problem is described in the stack trace:
Caused by: java.lang.NoSuchMethodException: com.buddhikajay.controller.NewTransactionDialogController.()
which basically says your controller class doesn't have a zero-argument constructor.
By default, the FXMLLoader will create the controller by calling its zero-argument constructor. Remove the constructor that you have defined in the controller class, or remove the parameters that it takes.
If you really need to pass arguments to the controller's constructor, you can either create the controller in Java code and pass it to the FXMLLoader:
NewTransactionDialogController controller = new NewTransactionDialogController(someValue);
FXMLLoader loader = new FXMLLoader();
loader.setLocation(...);
loader.setController(controller);
AnchorPane anchorPane = loader.load();
(Using this code, you must remove the fx:controller attribute from the FXML.)
Or, set a controller factory:
FXMLLoader loader = new FXMLLoader();
loader.setLocation(...);
loader.setControllerFactory(clazz -> {
if (clazz == NewTransactionDialogController.class) {
return new NewTransactionDialogController(someValue);
} else {
// default behavior:
try {
return clazz.newInstance();
} catch (Exception exc) {
throw new RuntimeException(exc);
}
}
});
AnchorPane anchorPane = loader.load();
(In this version, leave the fx:controller attribute in the FXML file.)
I was about to enter a different question as remarked by #James_D for my comment because Until I Read the first line of the FXML on this question, I had thought that I had a different problem.
For my sins, I reduced the challenge to a simple example of a single controller and two FXML files. One worked and the second fail/failed.
The starting point is the Netbeans sample "[Click me!]" sample. The code is pasted below. And, first a solution.
As preamble, let me say that it seems that everyone has been blaming the Java controller for these load errors. I had a bunch of errors like this on a project a couple of years ago. We exhausted "controller" debugging and eventually pressed-forward by re-building the FXML screens with ScendBuilder. I didn't have time to investigate further then.
Last week I perfectly working FXML screen started failing to load because we moved it to a runtime directory (previously it was in the JAR resources area).
KLUNK!
After 3 or 4 days tweaking that and this, I made a comment here on my error:
unknown path: 7
Javafx fxml LoadException: Error resolving onAction='#handleButtonAction', either the event handler is not in the Namespace or there is an error in the script.
On only the "simple.fxml" file, but not the "Scene.fxml" file. The file "simple.fxml" is reduced from the app FXML file that initially gave the problem. There were too many variables on that original file, so chop-chop-chop to match the canned demo.
When you use ONLY this:
xmlns:fx="http://javafx.com/fxml"
FXML load-s from files on disk under in your application folder work just like you want them to (well, like I want, anyway). Looking at the FXML above it is using a more 'fragile' namespace, viz.
Queston's original FXML:
<AnchorPane ...
xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1" ... >
By using diff, I slowly morphed "simple.fxml" to be as close as possible to "Scene.fxml", and "simple" just keeps failing to load. Please note; always using the same controller
Loading FXML with other metadata has not worked consistently an FXML file was moved. I don't have an explanation as to how this is so.
The FXML is kept in a directory called "test/resources/fxml/simple.fxml" for example. When I was building with both files in the project JAR, the 'same' FXML in both cases loaded and worked as expected. To me there's something un-said about aspects of the file load precess. Again for me, this is undesirable because the KEY value of a external scene definition would be interchange.
These kind of bear traps in XML mark-up that are (apparently) not picked up by development tools like SceneBuilder or the FXMLLoader() are barriers to progress on live projects that don't have slack to investigate esoteric weirdness like this.
This is witnessed by our previous project experience -- I was easier to re-edit a complex screen with SceneBuilder as a whole than track down load problems like this one. The call to action is: Diagnostics on FXML load -- an FXML Lint would be almost a requirement.
Controller, SimpleController.java:
package ex.view.views;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
public class SimpleController implements Initializable {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
The failing FXML started life as one of the Maven archetypes (I think) and that file worked fine until I moved the FXML files to a folder and loaded them from a InputStream.
I have formatted the AnchorPane markup on multiple lines for readability.
simple.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320"
xmlns="http://javafx.com/javafx/8.0.65"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="ex.view.views.SimpleController">
<children>
<Button fx:id="button" layoutX="126" layoutY="90" text="Click Me!" />
<Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
</children>
</AnchorPane>
The working FXML mark-up is from the Netbeans 8.1 samples.
Scene.fxml:
<?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="200" prefWidth="320"
xmlns:fx="http://javafx.com/fxml"
fx:controller="ex.view.views.SimpleController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>

JavaFX TextArea does not append text properly

I'm trying to build a simple calculator using TDD, so I have a TextArea that is right aligned to display the results and 20 buttons. Everytime one of the digit buttons are pressed it just appends the digit to the TextArea, the same thing was supposed to happen when I press the dot button. But instead it places the dot as the first character in the TextArea, only when I press a new digit the dot goes to its proper place.
So for example, if I press 9 and then 8 the TextArea shows "98", now if the dot is pressed the result will be ".98", finally if 7 is pressed the result is "98.7".
The expected result when I pressed the dot button should have been "98.".
I created a Minimal, Complete, and Verifiable example bellow
FXMLDocument.fxml:
<AnchorPane id="AnchorPane" prefHeight="175.0" prefWidth="256.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.141" fx:controller="mcv.FXMLDocumentController">
<children>
<Button fx:id="buttonNine" layoutX="14.0" layoutY="100.0" onAction="#handleButtonNine" prefHeight="60.0" prefWidth="69.0" text="9">
<font>
<Font size="24.0" />
</font></Button>
<TextArea fx:id="textArea" editable="false" focusTraversable="false" layoutX="15.0" layoutY="14.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" nodeOrientation="RIGHT_TO_LEFT" prefHeight="66.0" prefWidth="221.0" wrapText="true">
<font>
<Font size="35.0" />
</font>
</TextArea>
<Button fx:id="buttonDot" layoutX="169.0" layoutY="100.0" mnemonicParsing="false" onAction="#handleButtonDot" prefHeight="60.0" prefWidth="69.0" text=".">
<font>
<Font size="24.0" />
</font>
</Button>
</children>
</AnchorPane>
FXMLDocumentController.java:
#FXML
private TextArea textArea;
#Override
public void initialize(URL location, ResourceBundle resources) {
}
private void appenToResult(String ch){
textArea.appendText(ch);
}
#FXML
void handleButtonDot(ActionEvent event) {
appenToResult(".");
}
#FXML
void handleButtonNine(ActionEvent event) {
appenToResult("9");
}
As you can see the code is very simple. It should be working, my only clue is that this is a bug with the TextArea when the Node Orientation is set to RIGHT_TO_LEFT. If node orientation is set to INHERIT or LEFT_TO_RIGHT it works as expected. Thank you.

Add elements to a Stage from a different controller

I have a MainInterface.fxml, with its own controller MainController in which a button opens a new Stage from NewCrawler.fxml with its associated controller AddCrawlerController.
It looks fine, but i need to add stuff into the MainInterface using the interface NewCrawler .
The goal is adding a new "itemCrawler" each time someone press the "Start Crawling" button in NewCrawler, like the one hardcoded in MainInterface. How Can I do that?
MainController.java
public class MainController {
#FXML private AnchorPane mainPane;
#FXML
public void addCrawlerInstance(String domain) { //TODO dynamically add itemCrawler (Like the one hardcoded in MainInterface
Button b = new Button(domain); //it is only a try to add elements from a different controller
mainPane.getChildren().add(b);
}
#FXML
private void createCrawler () throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("guifxml/NewCrawler.fxml"));
Scene scene = new Scene(root);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
}
}
AddCrawlerController.java
public class AddCrawlerController { //ADD Button from Main Interface
#FXML private Button abortButton;
#FXML private Button addCrawlerButton;
#FXML
private void abortCurrentWindow () {
Stage currentStage = (Stage) abortButton.getScene().getWindow();
currentStage.close();
}
#FXML
private void addNewCrawler () throws Exception { //TODO ref. Maincontroller.AddCrawlerInstance
FXMLLoader loader = new FXMLLoader(getClass().getResource("guifxml/MainInterface.fxml"));
Parent root = loader.load();
String d = "prova";
MainController controller = loader.getController();
controller.addCrawlerInstance("prova");
}
}
MainInterface.fxml
<VBox fx:id="mainApp" maxWidth="600.0" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wsa.gui.MainController">
<children>
<ButtonBar maxWidth="643.0" nodeOrientation="RIGHT_TO_LEFT" prefHeight="40.0" prefWidth="643.0">
<buttons>
<Button alignment="CENTER" mnemonicParsing="false" text="Set Path" />
<Button alignment="CENTER" mnemonicParsing="false" text="Delete" />
<Button alignment="CENTER" mnemonicParsing="false" text="Stop" />
<Button alignment="CENTER" mnemonicParsing="false" text="Start" />
<Button alignment="CENTER" mnemonicParsing="false" onMouseClicked="#createCrawler" text="Add" />
</buttons>
<VBox.margin>
<Insets />
</VBox.margin>
<padding>
<Insets right="5.0" />
</padding>
</ButtonBar>
<AnchorPane fx:id="mainPane" maxHeight="-1.0" maxWidth="-1.0" nodeOrientation="LEFT_TO_RIGHT" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
<children>
<Separator layoutY="2.0" prefHeight="3.0" prefWidth="645.0" />
<Pane fx:id="itemCrawler" prefHeight="52.0" prefWidth="645.0">
<children>
<Text layoutX="44.0" layoutY="34.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Domain">
<font>
<Font size="20.0" />
</font>
</Text>
<TextField editable="false" layoutX="124.0" layoutY="13.0" prefHeight="25.0" prefWidth="319.0" text="http://www.prova.org" />
<Button alignment="CENTER" layoutX="456.0" layoutY="13.0" mnemonicParsing="false" text="Add URI" />
<Button alignment="CENTER" layoutX="528.0" layoutY="13.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="60.0" text="Explore" />
<CheckBox layoutX="14.0" layoutY="18.0" mnemonicParsing="false" prefHeight="17.0" prefWidth="17.0" />
<Separator layoutY="51.0" nodeOrientation="LEFT_TO_RIGHT" prefHeight="3.0" prefWidth="645.0" />
</children>
</Pane>
</children>
</AnchorPane>
</children>
</VBox>
NewCrawler.fxml
<AnchorPane fx:controller="wsa.gui.AddCrawlerController" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextArea layoutX="119.0" layoutY="89.0" prefHeight="237.0" prefWidth="467.0" />
<Text layoutX="44.0" layoutY="52.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Domain" wrappingWidth="74.13671875">
<font>
<Font size="20.0" />
</font>
</Text>
<TextField layoutX="119.0" layoutY="32.0" prefHeight="25.0" prefWidth="467.0" />
<Text layoutX="44.0" layoutY="111.0" strokeType="OUTSIDE" strokeWidth="0.0" text="URI list" textAlignment="CENTER" wrappingWidth="74.13672208786011">
<font>
<Font size="20.0" />
</font>
</Text>
<Text layoutX="119.0" layoutY="85.0" strokeType="OUTSIDE" strokeWidth="0.0" text="one URI on each line " textAlignment="CENTER" wrappingWidth="467.00000166893005" />
<Button fx:id="addCrawlerButton" layoutX="260.0" layoutY="353.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="115.0" onMouseClicked="#addNewCrawler" text="Start Crawling" />
<Button fx:id="abortButton" layoutX="118.0" layoutY="353.0" mnemonicParsing="false" onMouseClicked="#abortCurrentWindow" prefHeight="25.0" prefWidth="115.0" text="Abort" />
</children>
</AnchorPane>
MainInterface
NewCrawler
What I understand is that you need a dynamic list of itemCrawlers.
Instead of hardcoding a newCrawler, you should use a ListView with a custom CellFactory that constructs custom ListCell to represent itemCrawler.
This tutorial tells you how to do that : http://docs.oracle.com/javafx/2/ui_controls/list-view.htm
I am not 100% sure about this, so correct me if I am wrong.
In the NewCrawler's controller you load the FXML in its constructor. Then you can instantiate the NewCrawler controller and work with it as with any other object inside your MainController.

Why I'm getting javafx.fxml.LoadException even the path of the fxml file is correct

I get
javafx.fxml.LoadException:
When I'm loading and fxml file using following line of code.
AnchorPane anchorPane = (AnchorPane)loader.load()
This is my fxml file excluding import statements.
<AnchorPane prefHeight="537.0" prefWidth="374.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.buddhikajay.controller.NewTransactionDialogController">
<children>
<GridPane hgap="5.0" layoutX="30.0" layoutY="10.0" prefHeight="544.0" prefWidth="314.0" vgap="5.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="142.0" minWidth="10.0" prefWidth="69.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="226.0" minWidth="10.0" prefWidth="225.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="70.0" minHeight="10.0" prefHeight="33.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="105.0" minHeight="10.0" prefHeight="38.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="156.0" minHeight="10.0" prefHeight="51.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="154.0" minHeight="10.0" prefHeight="43.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="160.0" minHeight="10.0" prefHeight="43.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="161.0" minHeight="10.0" prefHeight="63.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="301.0" minHeight="10.0" prefHeight="180.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="231.0" minHeight="10.0" prefHeight="106.0" vgrow="SOMETIMES" />
</rowConstraints>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
<children>
<Label text="ID" />
<Label text="Date" GridPane.rowIndex="1" />
<Label text="Amont" GridPane.rowIndex="2" />
<Label text="Person" GridPane.rowIndex="4" />
<Label text="Type" GridPane.rowIndex="3" />
<Label text="Resolved" GridPane.rowIndex="5" />
<Label />
<Label text="Description" GridPane.rowIndex="6" />
<TextField fx:id="idTextField" GridPane.columnIndex="1" />
<TextField fx:id="dateTextField" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<TextField fx:id="amountTextField" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<TextArea fx:id="descriptionTextArea" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="225.0" spacing="20.0" GridPane.columnIndex="1" GridPane.rowIndex="7">
<GridPane.margin>
<Insets />
</GridPane.margin>
<padding>
<Insets bottom="10.0" left="20.0" right="10.0" top="10.0" />
</padding>
<children>
<Button fx:id="okButton" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#okActionFired" prefHeight="25.0" prefWidth="75.0" text="Ok" />
<Button fx:id="cancleButton" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#cancleActionFired" prefHeight="25.0" prefWidth="75.0" text="Cancle" />
</children>
</HBox>
<ComboBox fx:id="typeComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<ComboBox fx:id="personComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<ComboBox fx:id="resolvedComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="5" />
</children>
</GridPane>
</children>
</AnchorPane>
The compiler complains that there is an error in line number 1. I'm sure that the path of fxml file is correct. What is wrong with my code?
Here is the full error stack
javafx.fxml.LoadException:
/C:/Users/Buddhika/Documents/Programming/IdeaProjects/VirtualCreditDesktop/out/production/VirtualCreditDesktop/com/buddhikajay/view/NewTransactionDialog.fxml:9
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2595)
at javafx.fxml.FXMLLoader.access$700(FXMLLoader.java:104)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:928)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:967)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:216)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:740)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2701)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2521)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2435)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2403)
at com.buddhikajay.controller.NewTransactionDialogController.showNewTransactionDialog(NewTransactionDialogController.java:68)
at com.buddhikajay.controller.MainApp.start(MainApp.java:51)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$153(LauncherImpl.java:821)
at com.sun.javafx.application.LauncherImpl$$Lambda$50/1976027283.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$166(PlatformImpl.java:323)
at com.sun.javafx.application.PlatformImpl$$Lambda$46/301541210.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$164(PlatformImpl.java:292)
at com.sun.javafx.application.PlatformImpl$$Lambda$48/474926796.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$165(PlatformImpl.java:291)
at com.sun.javafx.application.PlatformImpl$$Lambda$47/1662429848.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$141(WinApplication.java:102)
at com.sun.glass.ui.win.WinApplication$$Lambda$38/519284171.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.InstantiationException: com.buddhikajay.controller.NewTransactionDialogController
at java.lang.Class.newInstance(Class.java:423)
at sun.reflect.misc.ReflectUtil.newInstance(ReflectUtil.java:51)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:923)
... 23 more
Caused by: java.lang.NoSuchMethodException: com.buddhikajay.controller.NewTransactionDialogController.<init>()
at java.lang.Class.getConstructor0(Class.java:3074)
at java.lang.Class.newInstance(Class.java:408)
... 25 more
The problem is described in the stack trace:
Caused by: java.lang.NoSuchMethodException: com.buddhikajay.controller.NewTransactionDialogController.()
which basically says your controller class doesn't have a zero-argument constructor.
By default, the FXMLLoader will create the controller by calling its zero-argument constructor. Remove the constructor that you have defined in the controller class, or remove the parameters that it takes.
If you really need to pass arguments to the controller's constructor, you can either create the controller in Java code and pass it to the FXMLLoader:
NewTransactionDialogController controller = new NewTransactionDialogController(someValue);
FXMLLoader loader = new FXMLLoader();
loader.setLocation(...);
loader.setController(controller);
AnchorPane anchorPane = loader.load();
(Using this code, you must remove the fx:controller attribute from the FXML.)
Or, set a controller factory:
FXMLLoader loader = new FXMLLoader();
loader.setLocation(...);
loader.setControllerFactory(clazz -> {
if (clazz == NewTransactionDialogController.class) {
return new NewTransactionDialogController(someValue);
} else {
// default behavior:
try {
return clazz.newInstance();
} catch (Exception exc) {
throw new RuntimeException(exc);
}
}
});
AnchorPane anchorPane = loader.load();
(In this version, leave the fx:controller attribute in the FXML file.)
I was about to enter a different question as remarked by #James_D for my comment because Until I Read the first line of the FXML on this question, I had thought that I had a different problem.
For my sins, I reduced the challenge to a simple example of a single controller and two FXML files. One worked and the second fail/failed.
The starting point is the Netbeans sample "[Click me!]" sample. The code is pasted below. And, first a solution.
As preamble, let me say that it seems that everyone has been blaming the Java controller for these load errors. I had a bunch of errors like this on a project a couple of years ago. We exhausted "controller" debugging and eventually pressed-forward by re-building the FXML screens with ScendBuilder. I didn't have time to investigate further then.
Last week I perfectly working FXML screen started failing to load because we moved it to a runtime directory (previously it was in the JAR resources area).
KLUNK!
After 3 or 4 days tweaking that and this, I made a comment here on my error:
unknown path: 7
Javafx fxml LoadException: Error resolving onAction='#handleButtonAction', either the event handler is not in the Namespace or there is an error in the script.
On only the "simple.fxml" file, but not the "Scene.fxml" file. The file "simple.fxml" is reduced from the app FXML file that initially gave the problem. There were too many variables on that original file, so chop-chop-chop to match the canned demo.
When you use ONLY this:
xmlns:fx="http://javafx.com/fxml"
FXML load-s from files on disk under in your application folder work just like you want them to (well, like I want, anyway). Looking at the FXML above it is using a more 'fragile' namespace, viz.
Queston's original FXML:
<AnchorPane ...
xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1" ... >
By using diff, I slowly morphed "simple.fxml" to be as close as possible to "Scene.fxml", and "simple" just keeps failing to load. Please note; always using the same controller
Loading FXML with other metadata has not worked consistently an FXML file was moved. I don't have an explanation as to how this is so.
The FXML is kept in a directory called "test/resources/fxml/simple.fxml" for example. When I was building with both files in the project JAR, the 'same' FXML in both cases loaded and worked as expected. To me there's something un-said about aspects of the file load precess. Again for me, this is undesirable because the KEY value of a external scene definition would be interchange.
These kind of bear traps in XML mark-up that are (apparently) not picked up by development tools like SceneBuilder or the FXMLLoader() are barriers to progress on live projects that don't have slack to investigate esoteric weirdness like this.
This is witnessed by our previous project experience -- I was easier to re-edit a complex screen with SceneBuilder as a whole than track down load problems like this one. The call to action is: Diagnostics on FXML load -- an FXML Lint would be almost a requirement.
Controller, SimpleController.java:
package ex.view.views;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
public class SimpleController implements Initializable {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
The failing FXML started life as one of the Maven archetypes (I think) and that file worked fine until I moved the FXML files to a folder and loaded them from a InputStream.
I have formatted the AnchorPane markup on multiple lines for readability.
simple.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320"
xmlns="http://javafx.com/javafx/8.0.65"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="ex.view.views.SimpleController">
<children>
<Button fx:id="button" layoutX="126" layoutY="90" text="Click Me!" />
<Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
</children>
</AnchorPane>
The working FXML mark-up is from the Netbeans 8.1 samples.
Scene.fxml:
<?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="200" prefWidth="320"
xmlns:fx="http://javafx.com/fxml"
fx:controller="ex.view.views.SimpleController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>

Resources