Design JavaFX View with FXML and Java Code - user-interface

I have created my view for a JavaFX project using FXML. I was wondering if it's possible to add a few more items to the view pragmatically in controller class?
For example, how can I add another set of Text and TextField in my controller file?
FXML
<AnchorPane prefHeight="400.0" prefWidth="228.0">
<children>
<Text layoutY="10.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Selected User:" GridPane.rowIndex="0" />
<Text layoutY="45.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Username :" GridPane.rowIndex="1" />
<TextField fx:id="username" layoutY="55.0" GridPane.rowIndex="2" />
<Text layoutY="100.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Address :" GridPane.rowIndex="3" />
<TextField fx:id="address" layoutY="110.0" GridPane.rowIndex="4" />
<Text layoutY="155.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Web Page :" GridPane.rowIndex="5" />
<TextField fx:id="WP" layoutY="165.0" GridPane.rowIndex="6" />
<Text layoutY="210.0" strokeType="OUTSIDE" strokeWidth="0.0" text="State :" GridPane.rowIndex="7" />
<Text layoutY="265.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Login Name :" GridPane.rowIndex="9" />
<TextField fx:id="login_Name" layoutY="275.0" GridPane.rowIndex="10" />
<Button fx:id="btnSave" layoutX="50.0" layoutY="320.0" mnemonicParsing="false" onAction="#btnSaveClicked" text="Save" />
<Button fx:id="btnSave" layoutX="35.0" layoutY="365.0" mnemonicParsing="false" onAction="#btnDeleteUserClicked" text="Delete User" />
<Button fx:id="btnAddNew" layoutX="30.0" layoutY="410.0" mnemonicParsing="false" onAction="#btnAddeNewClicked" text="Add New User" />
<TextField fx:id="state" layoutX="-2.0" layoutY="222.0" />
</children>
</AnchorPane>

Adding New Nodes in FXML
I would say, you should always add new nodes to the FXML unless you have a very good reason not to. Adding nodes to FXML is as easy as adding an extra line to the existing FXML.
<AnchorPane prefHeight="400.0" prefWidth="228.0">
<children>
...
<Text fx:id="newText"/>
<TextField fx:id="newTextField"/>
</children>
</AnchorPane>
These new nodes will be reflected in the scene graph instantaneously and you can bind them to the controller using their fx:id's.
Adding New Nodes in Controller
First, you should have a fx:id defined for the AnchorPane in order to access it in the controller.
<AnchorPane fx:id="anchorPane" prefHeight="400.0" prefWidth="228.0">
<children>
...
</children>
</AnchorPane>
You can then define the new controls and add them the to AnchorPane in the controller.
public class MyController implements Initializable {
#FXML
private AnchorPane anchorPane;
...
public void intialize() {
...
Text newText = new Text("Some Text");
TextField newTextField = new TextField();
anchorPane.getChildren().addAll(newText, newTextField);
...
}
}

Related

How to write Test cases for Javafx Controllers?

I have written this test class for javafx application.
class HelloApplicationTest extends GuiTest {
#Override
protected Parent getRootNode() {
Parent parent = null;
try {
parent = FXMLLoader.load((getResource("hello-view.fxml")));
return parent;
}
catch (IOException ex) {
}
return parent;
}
#Test
void add_button() {
Button add_btn_1=find("#add_btn");
assertFalse(add_btn_1.disableProperty().get());
FxAssert.verifyThat("#add_btn", LabeledMatchers.hasText("Add"));
}
}
I am getting error like this -> java.lang.NoSuchMethodError: 'java.util.Iterator javafx.stage.Window.impl_getWindows()'
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="350.0" prefWidth="666.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.fxml_db.HelloController">
<children>
<Label layoutX="14.0" layoutY="14.0" prefHeight="39.0" prefWidth="295.0" text="Add and View Employee:">
<font>
<Font name="System Bold" size="24.0" />
</font>
</Label>
<Label layoutX="22.0" layoutY="93.0" prefHeight="27.0" prefWidth="124.0" text="Name:" />
<Label layoutX="22.0" layoutY="136.0" prefHeight="27.0" prefWidth="124.0" text="Address:" />
<Label layoutX="22.0" layoutY="181.0" prefHeight="27.0" prefWidth="124.0" text="Age:" />
<TextField fx:id="name" layoutX="106.0" layoutY="94.0" />
<TextField fx:id="address" layoutX="106.0" layoutY="137.0" />
<TextField fx:id="age" layoutX="106.0" layoutY="182.0" />
<Button fx:id="add_btn" layoutX="127.0" layoutY="223.0" mnemonicParsing="false" onAction="#add_details" text="Add" />
<TableView fx:id="table" layoutX="342.0" layoutY="51.0" prefHeight="260.0" prefWidth="305.0">
<columns>
<TableColumn fx:id="idcol" prefWidth="39.33331298828125" text="ID" />
<TableColumn fx:id="namecol" prefWidth="111.3333740234375" text="Name" />
<TableColumn fx:id="addresscol" prefWidth="110.00003051757812" text="Address" />
<TableColumn fx:id="agecol" prefWidth="40.6666259765625" text="Age" />
</columns>
</TableView>
<Button fx:id="connect_db" layoutX="14.0" layoutY="310.0" mnemonicParsing="false" onAction="#connect" text="Connect DB" />
<Button layoutX="200.0" layoutY="223.0" mnemonicParsing="false" onAction="#clear_data" text="Clear" />
</children>
</AnchorPane>
I am not able to fetch the components form the .fxml file. this is my .fxml code

JavaFX Scene Builder Expand ScrollPane area at runtime when adding components to attached AnchorPane

I haven't been able to find info on this, but I've created a layout in Scene Builder, and I've placed an AnchorPane inside an empty ScrollPane, and added text, a slider, and a label in rows, and then added a button for the user to add a new entry of the above.
Basically a typical preference elicitation UI where the user can also add new entries and specify their own preference values as well.
When pressed, for testing purposes, the button creates a new label, adds it to the AnchorPane, and relocates it to a Y position outside the AnchorPane, and then resizes the AnchorPane so that the new label is included.
The problem that I'm having is that the ScrollPane doesn't adjust and expand the scrollable area to fit the new AnchorPane height, so I can't scroll down to where the new label is visible. In Scene Builder, on the other hand, if I resize the AnchorPane so that it's larger than the ScrollPane, the latter dynamically adjusts the scrollable area, so I'm not sure what the problem is.
Any help is appreciated.
EDIT:
As requested, below is a minimally reproducible version of the project.
Class that loads the FXML and creates the scene
package main;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.TitledPane;
import javafx.stage.Stage;
public class Registration_Page extends Application {
private Stage primaryStage;
private TitledPane mainLayout;
#Override
public void start(Stage primaryStage) throws IOException {
this.primaryStage = primaryStage;
showMainView();
}
private void showMainView() throws IOException {
FXMLLoader loader = new FXMLLoader(Registration_Page.class.getResource("resources/Registration_Page.fxml"));
mainLayout = loader.load();
Scene scene = new Scene(mainLayout);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Class that acts as the button controller, using FXML-defined components.
package main;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.AnchorPane;
public class ButtonController {
#FXML
private Button plus;
#FXML
private AnchorPane prefValuesAnchorPane;
#FXML
private ScrollPane scrollPane;
#FXML
protected void plusAction(ActionEvent event) {
Label lbl1 = new Label("Hello");
prefValuesAnchorPane.getChildren().add(lbl1);
lbl1.relocate(18, 250);
System.out.println(prefValuesAnchorPane.getHeight());
System.out.println(lbl1.getLayoutY());
if (lbl1.getLayoutY() >= prefValuesAnchorPane.getHeight())
{
prefValuesAnchorPane.resize(prefValuesAnchorPane.getWidth(), lbl1.getLayoutY() + 3);
}
}
}
The FXML document
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<TitledPane animated="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" text="User Registration" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.ButtonController">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TextField layoutX="52.0" layoutY="79.0" />
<Text layoutX="14.0" layoutY="96.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Name" />
<Text layoutX="14.0" layoutY="130.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Preference Values">
<font>
<Font size="14.0" />
</font>
</Text>
<ScrollPane fx:id="scrollPane" layoutX="14.0" layoutY="137.0" prefHeight="223.0" prefWidth="332.0">
<content>
<AnchorPane fx:id="prefValuesAnchorPane" minHeight="0.0" minWidth="0.0" prefHeight="217.0" prefWidth="329.0">
<children>
<Text layoutX="15.0" layoutY="30.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Val1:" />
<Slider blockIncrement="1.0" layoutX="115.0" layoutY="15.0" majorTickUnit="1.0" max="10.0" minorTickCount="0" prefWidth="140.0" showTickLabels="true" snapToPixel="false" snapToTicks="true" />
<Label layoutX="280.0" layoutY="12.0" text="0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Text layoutX="15.0" layoutY="62.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Val2:" />
<Slider blockIncrement="1.0" layoutX="115.0" layoutY="50.0" majorTickUnit="1.0" max="10.0" minorTickCount="0" prefWidth="140.0" showTickLabels="true" snapToTicks="true" />
<Label layoutX="280.0" layoutY="48.0" text="0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Text layoutX="15.0" layoutY="97.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Val3:" />
<Slider blockIncrement="1.0" layoutX="115.0" layoutY="85.0" majorTickUnit="1.0" max="10.0" minorTickCount="0" prefWidth="140.0" showTickLabels="true" snapToTicks="true" />
<Label layoutX="280.0" layoutY="82.0" text="0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Text layoutX="15.0" layoutY="133.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Val4:" />
<Slider blockIncrement="1.0" layoutX="115.0" layoutY="120.0" majorTickUnit="1.0" max="10.0" minorTickCount="0" prefWidth="140.0" showTickLabels="true" snapToTicks="true" />
<Label layoutX="280.0" layoutY="118.0" text="0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Button fx:id="plus" graphicTextGap="1.0" layoutX="289.0" layoutY="153.0" maxHeight="-Infinity" maxWidth="-Infinity" mnemonicParsing="false" onAction="#plusAction" prefHeight="0.0" prefWidth="30.0" text="+" textAlignment="CENTER" textOverrun="CENTER_ELLIPSIS" AnchorPane.topAnchor="153.0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Button>
</children>
</AnchorPane>
</content>
</ScrollPane>
<Button layoutX="532.0" layoutY="335.0" mnemonicParsing="false" text="Next" />
</children></AnchorPane>
</content>
</TitledPane>
The solution to this is to instead have a ScrollPane containing an AnchorPane (as it was), and for every entry added, create an AnchorPane or BorderPane or any other container pane (afaik), and add whatever to it, rather than adding components such as buttons or labels directly onto the original AP that's attached to the SP.

javafx: second stage with fxml doesn't react

I'm trying to use a searchbox in another stage by using fxml for the layout.
It it showing absolutely correct,but it doesn't react to any events.It seems that the elements are not found.
What is wrong with my code?
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
public class SearchBox{
//tabs
#FXML
private static TabPane frepl_tabPane=new TabPane();
#FXML
private static Tab frepl_tabReplace=new Tab();
#FXML
private static Tab frepl_tabSearch=new Tab();
//search
//search Controls
#FXML
private static TextField fr_searchInput=new Textfield();
#FXML
private static Button fr_find=new Button();
private static Stage stage = new Stage();
public static void display(String title) throws IOException {
Parent root = FXMLLoader.load(SearchBox.class.getResource("find_replace.fxml"));
Scene scene = new Scene(root);
stage.setTitle(title);
stage.setScene(scene);
stage.showAndWait();
frepl_tabPane.getSelectionModel().selectedItemProperty().addListener((obs,ov,nv)->{
//no reaction here
stage.setTitle(nv.getText());
System.out.println("pane was tabbed");
});
fr_find.setOnMouseClicked(e ->{
//no reaction here
System.out.println("search");
});
}
To open it i use (inside of the "initialize" function of another FXMLDocumentControler):
btn_search.setOnMouseClicked(e->{
try {
SearchBox.display("search");
} catch (IOException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
});
Here is the stack trace(when everything is non static e.g. the class,methods and fields). it appears,when i close the window.
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at SearchBox.display(SearchBox.java:133)
at FXMLDocumentController.lambda$A_table_buttons$22(FXMLDocumentController.java:1309)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3470)
at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3766)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:388)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
FXML file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="508.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TabPane fx:id="frepl_tabPane" layoutX="-1.0" layoutY="2.0" prefHeight="400.0" prefWidth="508.0" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab fx:id="frepl_tabSearch" text="Search">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TableView fx:id="fr_Stableview" layoutY="87.0" prefHeight="287.0" prefWidth="508.0">
<columns>
<TableColumn fx:id="fr_Sline" editable="false" prefWidth="75.0" sortable="false" text="Line" />
<TableColumn fx:id="fr_SColumn" editable="false" prefWidth="61.0" sortable="false" text="Column" />
<TableColumn fx:id="fr_SValue" editable="false" prefWidth="371.0" sortable="false" text="Value" />
</columns>
</TableView>
<TextField fx:id="fr_searchInput" layoutX="66.0" layoutY="13.0" prefHeight="25.0" prefWidth="250.0" />
<Label layoutX="3.0" layoutY="17.0" text="Search for:" />
<Button fx:id="fr_find" layoutX="324.0" layoutY="13.0" mnemonicParsing="false" text="Find" />
<Button fx:id="fr_findAll" layoutX="372.0" layoutY="13.0" mnemonicParsing="false" text="Find All" />
<CheckBox fx:id="fr_matchCaseS" layoutX="324.0" layoutY="53.0" mnemonicParsing="false" text="Match case (Aa)" />
<Label fx:id="fr_foundS" layoutX="8.0" layoutY="70.0" text="found: 5" underline="true">
<font>
<Font name="System Bold Italic" size="12.0" />
</font>
</Label>
</children>
</AnchorPane>
</content>
</Tab>
<Tab fx:id="frepl_tabReplace" text="Replace">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TableView fx:id="fr_tableviewR" layoutY="107.0" prefHeight="267.0" prefWidth="508.0">
<columns>
<TableColumn fx:id="fr_lineR" prefWidth="75.0" text="Line" />
<TableColumn fx:id="fr_ColumnR" prefWidth="61.0" text="Column" />
<TableColumn fx:id="fr_ValueR" prefWidth="371.0" text="Value" />
</columns>
</TableView>
<CheckBox fx:id="fr_matchCaseR" layoutX="347.0" layoutY="59.0" mnemonicParsing="false" text="Match case (Aa)" />
<Label layoutX="3.0" layoutY="17.0" text="Search for:" />
<Button fx:id="fr_replace" layoutX="347.0" layoutY="11.0" mnemonicParsing="false" text="Replace" />
<TextField fx:id="fr_replaceInput" layoutX="82.0" layoutY="13.0" prefHeight="25.0" prefWidth="250.0" />
<Button fx:id="fr_replaceAll" layoutX="412.0" layoutY="11.0" mnemonicParsing="false" text="Replace All" />
<TextField fx:id="fr_replaceAllInput" layoutX="82.0" layoutY="55.0" prefHeight="25.0" prefWidth="250.0" />
<Label layoutX="3.0" layoutY="59.0" text="Replace with:" />
<Label fx:id="fr_replacedR" layoutX="3.0" layoutY="90.0" text="replaced: 5" underline="true">
<font>
<Font name="System Bold Italic" size="12.0" />
</font>
</Label>
</children>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
</children>
</Pane>

root node (TreeItem) not showing in TreeView

I create TreeView in .fxml file and then i am trying to show root node. but it's not showing.
Here is my code.
<TabPane prefHeight="289.0" prefWidth="246.0" styleClass="tab-pane" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<stylesheets>
<URL value="#main.css" />
</stylesheets>
<tabs>
<Tab text="TestBed Explorer">
<content>
<AnchorPane id="Content" fx:id="soariteAnchorScollparent" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<ScrollPane fx:id="soariteTreeScrollPane" prefHeight="259.0" prefWidth="246.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content>
<AnchorPane id="Content" fx:id="soariteTreeAnchorPane" minHeight="0.0" minWidth="0.0" prefHeight="249.0" prefWidth="73.0">
<children>
<TreeView fx:id="soariteTree" prefHeight="245.0" prefWidth="79.0" showRoot="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="167.0" AnchorPane.topAnchor="0.0">
<TreeItem expanded="true" value="categories" fx:id="rootTreeItem" />
</TreeView>
</children>
</AnchorPane>
</content>
</ScrollPane>
</children>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
I also give reference of this in main class like.
public class Mainextends Application {
#FXML
public TreeView<String> soariteTree;
#FXML
public TreeItem<String> rootTreeItem;
Please give me any reference or hint.
You have done a small mistake with fxml,
you can see you have written AnchorPane.rightAnchor="167.0" which is making your tree view disappear (and same small mistakes with width of anchor pane and tree view).
replace your of scroll pane with,
<ScrollPane fx:id="soariteTreeScrollPane" prefHeight="259.0" prefWidth="246.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content>
<AnchorPane id="Content" fx:id="soariteTreeAnchorPane" minHeight="0.0" minWidth="0.0" prefHeight="-1.0" prefWidth="-1.0">
<children>
<TreeView fx:id="soariteTree" prefHeight="-1.0" prefWidth="-1.0" showRoot="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<TreeItem expanded="true" value="categories" fx:id="rootTreeItem" />
</TreeView>
</children>
</AnchorPane>
</content>
</ScrollPane>
UPDATE :- Handling of Mouse Event
soariteTree.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.getButton().equals(MouseButton.SECONDARY)) {
System.out.println(">> " + event.getEventType());
}
}
});
your fxml will be,
<TreeView fx:id="categoryTreeView" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minWidth="200.0" prefHeight="-1.0" prefWidth="200.0" showRoot="true" styleClass="master-tree" VBox.vgrow="ALWAYS">
<TreeItem expanded="true" value="categories" fx:id="categoryTreeItem" />
</TreeView>
And Your Controller will be,
public class MyClass extends Application {
#FXML private TreeItem<ItemMaster> categoryTreeItem;
#FXML private TreeView<ItemMaster> categoryTreeView;
So you dont need to create a root for your tree. And you are done.

Zk how to reach included .zul page component by id?

I can't reach component by id in the included .zul page. I have one main.zul with a controller and I need to get a component in included zul page through the java controller class, but it returns null.
I know the included method creates new id space but is there any way to get this component?
UPDATE
Here is my code:
the main zul page
<?page title="DealerVizard.zul"?>
<?page id="main" ?>
<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c"?>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" arg0="./Dealer" ?>
<zk>
<style src="/resources/css/default.css" />
<window id="Dealer" class="index"
apply="com.i2i.prm.controller.IndexController">
<div class="content" width="100%">
<tabbox id="tb" forward="onSelect=onSelect">
<tabs id="tabs">
<tab id="info" label="INFO" />
<tab id="create" label="CREATE" />
<tab id="edit" label="EDIT" />
<tab id="test" label="TEST PANEL(LIST BOX)" />
</tabs>
<tabpanels>
<tabpanel id="DealerInfo">
<include id="DealerInfoContent"
src="View/Dealer/DealerInfo.zul" />
</tabpanel>
<tabpanel id="DealerCreate">
<include id="DealerCreateContent"
src="View/Dealer/DealerCreate.zul" />
</tabpanel>
<tabpanel id="DealerEdit">
<include id="DealerEditContent"
src="View/Dealer/DealerEdit.zul" />
</tabpanel>
<tabpanel id="PagingListBox">
<include id="PagingListBoxContent" // Included here
src="View/TEST/PagingListBox.zul" />
</tabpanel>
</tabpanels>
</tabbox>
</div>
</window>
</zk>
PagingListBox.zul (Included page)
<?page id="list" ?>
<zk>
<grid width="100%">
<columns>
<column label="" />
</columns>
<rows>
<row>
<listbox id="listModel" width="100%" height="100%"
visible="true" span="true" pagingPosition="top" rows="20"
selectedItem="#{DealerController.selected}"
model="#{DealerController.userList}"
forward="onSelect=//main/Dealer.onSelect">
<auxhead>
<auxheader colspan="1">
<textbox
value="#{DealerController.searchUser.name}" maxlength="9"
id="searchCO_ID" forward="onChanging=//main/Dealer.onSearch"
width="100%">
</textbox>
</auxheader>
<auxheader colspan="1">
<textbox
value="#{DealerController.searchUser.surname}" maxlength="21"
id="searchMSISDN" forward="onChanging=//main/Dealer.onSearch"
width="100%">
</textbox>
</auxheader>
<auxheader colspan="1">
</auxheader>
</auxhead>
<listhead>
<listheader label="Name"
sort="auto(UPPER(name))" />
<listheader label="Surname"
sort="auto(UPPER(surname))" />
<listheader label="Delete ?" />
</listhead>
<listitem self="#{each=USERLIST}">
<listcell>
<label value="#{USERLIST.user.name}" />
<textbox
value="#{DealerController.tmpUser.name}" visible="false" />
</listcell>
<listcell>
<label value="#{USERLIST.user.surname}" />
<textbox
value="#{DealerController.tmpUser.surname}" visible="false" />
</listcell>
<listcell>
<button label="Update"
forward="onClick=//main/Dealer.onUpdate" visible="false" />
<button image="icons/edit-delete.png"
label="Delete" forward="onClick=//main/Dealer.onDelete"
width="100%" disabled="true" />
<button label="Save"
forward="onClick=//main/Dealer.onSave" visible="false" />
<button label="Cancel"
forward="onClick=//main/Dealer.onCancel" visible="false" />
</listcell>
</listitem>
</listbox>
<paging id="pagingData" pageSize="20" />
</row>
</rows>
</grid>
</zk>
IndexCOntroller.java
public class IndexController extends GenericForwardComposer {
private List<User> userList = new ArrayList<User>() ;
AnnotateDataBinder binder;
Tabbox tb;
Window Dealer;
private int pageCount=0;
#Override
public void doAfterCompose(Component comp) throws Exception {
// TODO Auto-generated method stub
super.doAfterCompose(comp);
comp.setVariable(comp.getId() + "Controller", this, true);
binder = (AnnotateDataBinder) Dealer.getVariable("binder", true);
System.out.println(Path.getComponent("//list/listModel"));
}
public IndexController() {
// TODO Auto-generated constructor stub
}
}
Normally I wouldn't recommend using Path.getComponent() way to access other components as your application code becomes tightly coupled with your component structure in your view page.
In your case you simplest way is to use AbstractComponent#getFellow(String compId) method so for eg.
Include inc = (Include) Dealer.getFellow("PagingListBoxContent");
Listbox listModel = (Listbox) inc.getFellow("listModel");
System.out.println(listModel);
So in future even if you insert any other component in your ZUML page before your listbox your code will still work.
UPDATE: BTW there was an interesting blogpost on this very topic on ZK blog recently
if your include have id, you can use dollar sign to get the inner components
<zk>
<include id="inc" src="test.zul />
</zk>
test.zul
<zk>
<label id="lab1" value="test1" />
</zk>
you can use "inc$lab1" get the label in test.zul
You can access any component in any other id space using zscript or java. if it is on the same page, but different window then (component B in window A):
Path.getComponent("/A/B");
if it is on a different page then (component B in window A on page P):
Path.getComponent("//P/A/B");
You can find documentation here: http://books.zkoss.org/wiki/ZK%20Developer%27s%20Reference/UI%20Composing/ID%20Space
You can add in your IndexController.java:
...
private Include DealerInfoContent;
...
this way you can access the included component within the parent composer.
(I would suggest to use camelCase ids for it, though).

Resources