Getting Started with JavaFX - javafx

Hello,when I study JavaFX in "Using FXML to Create a User Interface" https://docs.oracle.com/javase/8/javafx/get-started-tutorial/fxml_tutorial.htm
I want to write a demo like a simple calculator.
when I use the GridPane layout, it can not have an error,
but when I use the Pane layout, it showed the error "No Controller specified for top-level element" in the sample.fxml.
I do not understand it
I tried another way that I did not use FXML, wrote code in the Main.java like this

if you use action in fxml you will need to specify what class will be used to find this method, usually by attribute in root element like this
<GridPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
more about https://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html#controller_method_event_handlers
or can use the method in FXMLoader when you have to use special instance
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
loader.setController(new Controller());
Parent root = loader.load();

Related

Is it possible to add a new node or parent to an already loaded fxml file in javafx?

I'm recently writing a javafx application and in one of its parts the client must wait for the server to get a list of people and after getting the list it must be used in a listview that is going to be added to a parent. That parent is and fxml file and after loading it I want to know if it is possible to add the vbox containing the listview to the parent or not. I'd be grateful if anyone could help...
From your question I gather you are not familiar with the idea of a controller or the associated FXML injection performed by a FXMLLoader. This answer by James_D goes over the very basics of the JavaFX lifecycle but it first goes over the basics of the procedure involved when loading a FXML file. If you want to modify the scene-graph that is loaded via FXML then you need to use a controller class with the appropriate FXML annotated fields. For example, let's say your parent is a BorderPane. In your FXML file you'd have:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane fx:id="parent" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/10.0.1"
fx:controller="some.package.YourController">
<top>
<!-- maybe have something like a MenuBar here -->
</top>
<bottom>
<!-- maybe have a some type of status bar here -->
</bottom>
</BorderPane>
Notice the fx:controller attribute; it is the class name of the class to instantiate and use as a controller. Also note the fx:id attribute. In your controller class you'd have:
package some.package;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXML;
public class YourController {
#FXML
private BorderPane parent; // field name matches the fx:id attribute
#FXML
private void initialize() {
// do any initializing if needed (if not, get rid of this method)
// you can access and modify any FXML injected field from this method
}
}
Then you can use the parent via the controller instance. You could also create and link event handler methods in the controller and do certain behavior based on user actions. It's important to note, however, that how you change the state of the UI in the controllers depends on how you access you model classes. You'll need to have the model available to your controller and possibly have it shared between mutliple controllers. There are a decent number of questions/answers on Stack Overflow about how to do this already.
Here is another resource that may help you: Introduction to FXML.

Java FX multiple scenes crash [duplicate]

New to javaFx and wanting to use scenebuilder for GUI development, i've come across an issue with no luck searching the website nor the web in general for my problem, although similar questions have been asked, thought a different perspective could be needed. I am trying to load an FXML file through Netbeans after a quick build to test functionality so the code is simple, but i cannot get the root file to be set in the controller. my code is the following
public class Divergex extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("DivergexGUI.fxml"));
Scene scene = new Scene(root);
scene.setRoot(root);
stage.setScene(scene);
stage.show();
}
Ive tried suggestions in changing fxroot to a Vbox with no luck, i continue to get a Load exception on the compile :
Exception in Application start method...
Caused by: javafx.fxml.LoadException: Root hasn't been set. Use method setRoot() before load.
yet when i use
scene.setRoot(root);
the same exception is experienced
i've narrowed the issue down to the fact that my FXML file is unable to be set as a root in the Parent object but have had no luck in tackling this. Any suggestions would be great thanks.
<fx:root> specifies a "dynamic root" for your FXML file; this means the root of the FXML file is an object that is set on the loader prior to loading the file. This is typically used for custom controls, where you want the control to be a subclass of Node that can be instantiated using regular Java code, but want to define its layout using FXML. Proper use of <fx:root> (or at least an example of how it can be used) is shown in the standard documentation. In particular, if you use <fx:root> you must:
Create an FXMLLoader instance, instead of using the static convenience FXMLLoader.load(URL) method
Call setRoot(...) on that instance, and pass in the object that is to be the root of the FXML.
For standard FXML use, you just use a regular instance declaration as the root. Almost every example available works this way: probably the best place to start is the official tutorial. In your case, since you want a VBox, you probably just need
<VBox xmlns="javafx.com/javafx/8"; xmlns:fx="javafx.com/fxml/1"; fx:controller="divergex.DivergexGUIController">
<!-- ... -->
</VBox>
Edit If Netbeans is giving you issues, I recommend using Eclipse with the e(fx)clipse plugin. There's a very barebones, but pretty much all you need, tutorial.
uncheck id::root in scence builder
or change id::root to vbox
Just you should not use fx:root construct in scene builder.
so remove this line of code from the fxml file.
For example: <fx:root prefHeight="246.0" prefWidth="479.0" type="AnchorPane" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.mycontroller">
When you create FXML file with the help of Scene Builder. It uses fx: root as a pane. Replace it with Anchor Pane
AnchorPane xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.controller.Controller
It works for me. Anyone can try, it may help for you

Scene Builder 2.0. FXML import not working

I'm using JavaFX Scene Builder 2.0. version and I would like to import a FXML file under TabPane controller. My idea is that I will have one kind of container FXML file with TabPane and separate FXML files for things that will come inside of tabs. When I try to import FXML file where I have things that I would like to add under one tab, Scene Builder gives error message "Failed to import TabContents.fxml under TabPane". Why it is not possible to import anything under the TabPane? If I import same file directly under root StackPane everything works.
EDIT: While the below works, it is best to add some sort of layout pane (like an AnchorPane) to each tab in your TabPane, select the AnchorPane pane in the hierarchy view on the left and then import your other fxml document into that, as opposed to importing directly into a TabPane (Perhaps if the root node of the document is a Tab it would work?).
Looks like a bug, for now:
Cut your entire document hierarchy
Add an empty stack pane
Include your other FXML file
Paste your document hierarchy into the stack pane
Drag your FXML file into the appropriate place in your hierarchy
Cut your new hierarchy (with your file included)
Delete the now defunct stack pane
Paste your hierarchy back in
And voila, working as intended!
Three simple steps
Add a StackPane to the content area of your Tab, ensuring that it occupies 100% of the area.
Go to the Hierarchy view and select that StackPane you just added.
Include your TabContents.fxml. It should automatically be added to the created StackPane and should display as desired.
Also, to answer your additional question, importing it directly into the TabPane will render it as a Graphic rather than a Node.
just add a new TabPane where you want and then edit your FXML code of the TabPane just added as following:
<TabPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="5000.0" prefWidth="5000.0" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab closable="false" text="MyTab1">
<content>
<fx:include source="MyTab1.fxml" />
</content>
</Tab>
<Tab closable="false" text="MyTab2">
<content>
<fx:include source="MyTab2.fxml" />
</content>
</Tab>
</tabs>
</TabPane>
adding as many tab you need just adding more 'Tab' tags.
'MyTab1.fxml' and 'MyTab2.fxml' are just fxml files contained in the same folder of the fxml file of the TabPane.
it works for me selecting first the root node in the scene. Then I import de FXML and it is imported hanging from this root node. As the last step, I move the imported FXML to the place I want in the scene.
I realised that the FXML import can also fail when you have another FXML template included in the one you want to import. Something like:
<fx:include source="top-menu-bar.fxml" />
Looks like SceneBuilder doesn't know where is top-menu-bar.fxml. The solution can be to work on the template separately and then adding those includes manually to make it works.
It works for me:
<AnchorPane prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" >
<children>
<fx:include fx:id="includeID" source="includeSource.fxml" />
</children>
</AnchorPane>
The include file must be include in the children of a pane.

get FXML file nodes using java code

How to get elements or nodes from FXML file using Java, I know the way by using initialization or by setting controller class in FxmL . But I need to do it without any controller. I want to access the nodes inside the fxml file using.
My FXML COde:
HBox fx:id="hbx" id="hbx" alignment="CENTER_RIGHT" prefHeight="100.0"
prefWidth="200.0" BorderPane.alignment="CENTER"
My java Code
System.out.println(par.lookupAll("hbx"));
See my Code above, could you give me a hint?
After loading the FXML file, you can use Node#lookup():
Node node = fxmlParentPane.lookup("#nodeId");

What are the pros and cons FXML?

What are the pros and cons of using FXMLs or not using FXMLs for developing JavaFX applications?
For developing enterprise JavaFX application which approach should one follow?
FXML Cons: It takes slightly longer to load and display.
FXML Pros:
Rapid scene development / mock up using Scene Builder.
FXML is not a compiled language; you do not need to recompile the code to see the changes. Just reload the FXML file.
It provides a clear separation of GUI from logic/controller.
So you can have different versions of a scene/view using the same controller. This is handy for demo's for instance.
The content of an FXML file can be localized as the file is read.
Definitely use FXML in enterprise apps !
I would add two contra to Jurgens list.
If you are working with FXML instantiation of your view is sort of inconvenient. At least from my point of view.
Node explorer = new MyExplorerWidget();
or
Node explorer = cdicontainer.newInstance(MyExplorerWidget.class);
is more pleasant than
FXMLLoader loader = new FXMLLoader(getClass().getResource("com.mycompany.some.very.long.name.MyExplorerWidget.fxml"),explorerwidgetresouces);//Of course we want our app internationalized
Node explorer = loader.load();
Another point is that FXML is static. If you want to generate your UI at run time depending on some model you will write UI code anyway. I ended up with useless fxml files like this PropertyGrid.fxml
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="PropertyGridController">
<children>
<VBox fx:id="vbox" layoutX="63.0" layoutY="-28.0" prefHeight="172.0" prefWidth="163.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
And the PropertyGridController.
public class PropertyGridController{
#FXML
VBox vbox;
....
public void setModel(PropertySheet model){
//.... tons of code to generate the actual property grid and add it to the view
}
}

Resources