I'm trying to create a grid/tile like page using HBoxes and display text inside of the HBoxes, but the children(Label and Button) are restricted to the top leftof the HBox. I've been using scenebuilder, but even when I set the Layout X and Y the children stay in the same positions. All of the HBoxes have this problem.
FXML Example
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox prefHeight="800.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.improved.HelloController">
<children>
<HBox fx:id="hBox" prefHeight="100.0">
<children>
<TabPane prefHeight="100.0" prefWidth="${hBox.width}" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab text="Home">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0">
<children>
<HBox fx:id="lastRaceHBox" prefHeight="386.0" prefWidth="400.0">
<children>
<VBox>
<children>
<Button mnemonicParsing="false" onAction="#onHelloButtonClick" text="Hello!" />
<Label fx:id="welcomeText" prefHeight="17.0" prefWidth="68.0" />
</children>
</VBox>
</children></HBox>
<HBox fx:id="nextRaceHBox" layoutX="400.0" prefHeight="386.0" prefWidth="400.0" />
<HBox fx:id="upcomingDatesHBox" layoutX="800.0" prefHeight="386.0" prefWidth="400.0" />
<HBox fx:id="rankingsHBox" layoutY="386.0" prefHeight="386.0" prefWidth="400.0" />
<HBox fx:id="goalsHBox" layoutX="400.0" layoutY="386.0" prefHeight="386.0" prefWidth="400.0" />
<HBox fx:id="playerInfoHBox" layoutX="800.0" layoutY="386.0" prefHeight="386.0" prefWidth="400.0" />
</children>
</AnchorPane>
</content>
</Tab>
<Tab text="Dates">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Race">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Player Info">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Player Search">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
</tabs>
</TabPane>
</children>
</HBox>
</children>
</VBox>
Controller Class
package com.example.improved;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class HelloController {
#FXML
private Label welcomeText;
#FXML
protected void onHelloButtonClick() {
welcomeText.setText("Welcome to JavaFX Application!");
}
}
Main Application Class
package com.example.improved;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
#Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("MainMenu.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 1280, 960);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
Is there any way to freely move the children?
The HBox API outlines the available constraints. In particular, "The alignment of the content is controlled by the alignment property, which defaults to Pos.TOP_LEFT." You can specify the desired Pos value. You may also want to experiment with the settings that control Resizable Range and Optional Layout Constraints.
As a concrete example, LayoutSample.java, illustrated here, specifies a grow constraint that allows helpIcon to stay on the right as the stage is resized:
HBox.setHgrow(stack, Priority.ALWAYS);
More examples are seen here.
Related
I'm trying to create a TabView in JavaFX. I would like to have some of the tabs distanced from the other tabs, since their functions belong to another category.
This is what it looks like now:
And as you can see I want the two last tabs to be moved to the right side without affecting the rest.
Here's my FXML-file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?>
<?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.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Application.MainController">
<center>
<VBox alignment="BOTTOM_CENTER" prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER">
<children>a
<TabPane accessibleRole="BUTTON" nodeOrientation="LEFT_TO_RIGHT" prefHeight="651.0" prefWidth="1000.0" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab text="Courses">
<content>
<TableView prefHeight="665.0" prefWidth="1000.0">
<columns>
<TableColumn prefWidth="75.0" text="C1" />
<TableColumn prefWidth="75.0" text="C2" />
</columns>
</TableView>
</content>
</Tab>
<Tab text="Education Matrix">
<content>
<TableView prefHeight="200.0" prefWidth="200.0">
<columns>
<TableColumn prefWidth="75.0" text="C1" />
<TableColumn prefWidth="75.0" text="C2" />
</columns>
</TableView>
</content>
</Tab>
<Tab text="Employee">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Calendar">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab fx:id="companiesTab" text="Companies">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab fx:id="providerTab" text="Provider">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
</tabs>
<VBox.margin>
<Insets />
</VBox.margin>
</TabPane>
</children>
</VBox>
</center>
<bottom>
<GridPane prefHeight="105.0" prefWidth="1000.0" BorderPane.alignment="CENTER">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: grey;">
<children>
<Button mnemonicParsing="false" text="Button" />
</children>
<padding>
<Insets left="20.0" />
</padding>
</HBox>
<HBox alignment="CENTER_RIGHT" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: grey;" GridPane.columnIndex="2">
<children>
<Button mnemonicParsing="false" text="Button" />
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
<padding>
<Insets right="20.0" />
</padding>
</HBox>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: grey;" GridPane.columnIndex="1">
<children>
<Button mnemonicParsing="false" text="Button" />
</children>
</HBox>
</children>
</GridPane>
</bottom>
<top>
<GridPane prefHeight="106.0" prefWidth="1000.0" BorderPane.alignment="CENTER">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="494.0" minWidth="10.0" prefWidth="289.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="711.0" minWidth="10.0" prefWidth="711.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0">
<children>
<ChoiceBox prefWidth="150.0" />
</children>
<padding>
<Insets left="20.0" />
</padding>
</HBox>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<Label text="Smart Academy Manager">
<font>
<Font name="Arial" size="31.0" />
</font>
</Label>
</children>
</HBox>
</children>
</GridPane>
</top>
</BorderPane>`enter code here`
Original TabPane does not provide tools for custom tab layout. But a similar result can be obtained using some trick.
You can set invisible Tab into required place and bind it's width with width of the TabPane.
First we need to calc splitter's width. This is the width of the TabPane minus the sum of the widths of the Tabs, excluding the splitter. Tab object can be obtained as Node from TabPane using the command .lookup(). We also need to consider the width associated with the styles (padding, spacing). For this example I will set this number by hard (for default theme). After calcs we set size of the splitter using .setStyle():
private void autoSizeSplitter(TabPane tabPane, Tab splitter) {
double width = tabPane.getWidth();
Set<Node> tabs = tabPane.lookupAll(".tab");
for (Node node : tabs) {
if (node.getId() == null || !node.getId().equals(splitter.getId())) {
width = width - node.getBoundsInParent().getWidth();
}
}
double PADDING = 20;
width = width - PADDING;
splitter.setStyle("-fx-background-color:transparent; -fx-pref-width: " + width + ";");
}
Finally we set the listener on the TabPane width property and autosize splitter for first time in initialization:
tabPane.widthProperty().addListener(observable -> autoSizeSplitter(tabPane, splitter));
Platform.runLater(() -> autoSizeSplitter(tabPane, splitter));
Full example:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.stage.Stage;
import java.util.Set;
public class Sample extends Application {
#Override
public void start(Stage primaryStage) {
TabPane tabPane = new TabPane();
tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
Tab splitter = new Tab();
splitter.setDisable(true);
splitter.setId("splitter");
tabPane.getTabs().add(new Tab("111"));
tabPane.getTabs().add(new Tab("222"));
tabPane.getTabs().add(splitter);
tabPane.getTabs().add(new Tab("333"));
tabPane.getTabs().add(new Tab("444"));
tabPane.getTabs().add(new Tab("555"));
Scene scene = new Scene(tabPane, 640, 480);
primaryStage.setScene(scene);
primaryStage.show();
tabPane.widthProperty().addListener(observable -> autoSizeSplitter(tabPane, splitter));
Platform.runLater(() -> autoSizeSplitter(tabPane, splitter));
}
private void autoSizeSplitter(TabPane tabPane, Tab splitter) {
double width = tabPane.getWidth();
Set<Node> tabs = tabPane.lookupAll(".tab");
for (Node node : tabs) {
if (node.getId() == null || !node.getId().equals(splitter.getId())) {
width = width - node.getBoundsInParent().getWidth();
}
}
double PADDING = 20;
width = width - PADDING;
splitter.setStyle("-fx-background-color:transparent; -fx-pref-width: " + width + ";");
}
public static void main(String[] args) {
launch(args);
}
}
I'm new to java Fx. I have a TabPanel with 3 Tabs. Each Tab has many controls (text, buttons, etc.), and what I want is to assign a one controller for all Tab. The SceneBuilder only let me assign a controller for the whole view, I mean, only the top panel (the root) has the "Controller class" option, so How to write the code for all the tabs in one class.
i have .fxml file as:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<Pane lns="http://javafx.com/javafx/8"xmlns:fx="http://javafx.com/fxml/1"
fx:controller="Application.LoginController">
<children>
<TabPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight=" -
Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0"
tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab text="Register">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0"
prefWidth="200.0">
<children>
<Label layoutX="27.0" layoutY="45.0" text="Name" />
<Label layoutX="27.0" layoutY="102.0" text="Password"
/>
<Label layoutX="27.0" layoutY="151.0" text="City" />
<Label layoutX="27.0" layoutY="204.0" text="Email" />
<Label layoutX="27.0" layoutY="246.0" text="Phone" />
<TextField fx:id="name"
layoutX="164.0"layoutY="41.0"/>
<TextField fx:id="passwd" layoutX="164.0"
layoutY="98.0" />
<TextField fx:id="city" layoutX="164.0"
layoutY="147.0" />
<TextField fx:id="email" layoutX="164.0"
layoutY="200.0" />
<TextField fx:id="phone" layoutX="164.0"
layoutY="242.0" />
<Button fx:id="register" layoutX="129.0"
layoutY="308.0" mnemonicParsing="false" text="Register" />
<Button fx:id="cancle" cancelButton="true"
layoutX="274.0" layoutY="308.0" mnemonicParsing="false" text="Cancle" />
</children>
</AnchorPane>
</content>
</Tab>
<Tab text="Login">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0"
prefWidth="200.0">
<children>
<Label layoutX="26.0" layoutY="57.0" text="User Name"
/>
<Label layoutX="26.0" layoutY="103.0" text="Password"
/>
<Button fx:id="myLogin" layoutX="145.0"
layoutY="186.0" mnemonicParsing="false" text="Login" />
<Button fx:id="cancle" cancelButton="true"
layoutX="274.0" layoutY="186.0" mnemonicParsing="false" text="Cancle" />
<TextField fx:id="uName" layoutX="145.0"
layoutY="53.0" prefHeight="25.0" prefWidth="205.0" />
<TextField fx:id="pwd" layoutX="148.0" layoutY="99.0"
prefHeight="25.0" prefWidth="200.0" />
</children>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
</children>
</Pane>
This app demonstrates how to use a controller to interact with different Nodes in different Tabs in a TabPane.
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication151 extends Application
{
#Override
public void start(Stage stage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
Controller
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
/**
*
* #author blj0011
*/
public class FXMLDocumentController implements Initializable
{
//Tab1 nodes
#FXML private Label lblTab1;
#FXML private TextField tfTab1;
//Tab2 nodes
#FXML private Label lblTab2;
#FXML private TextField tfTab2;
#Override
public void initialize(URL url, ResourceBundle rb)
{
//This code set the Tab1 label's text to what is show in the TextField on Tab1
tfTab1.setOnKeyReleased((event)->{
lblTab1.setText(tfTab1.getText());
});
//This code set the Tab2 label's text to what is show in the TextField on Tab2
tfTab2.setOnKeyReleased((event)->{
lblTab2.setText(tfTab2.getText());
});
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.StackPane?>
<AnchorPane id="AnchorPane" prefHeight="353.0" prefWidth="588.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.111" fx:controller="javafxapplication151.FXMLDocumentController">
<children>
<Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
<TabPane layoutX="87.0" layoutY="20.0" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<tabs>
<Tab text="Untitled Tab 1">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TextField fx:id="tfTab1" layoutX="184.0" layoutY="84.0" prefHeight="25.0" prefWidth="220.0" />
<StackPane layoutX="27.0" layoutY="143.0" prefHeight="150.0" prefWidth="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<children>
<Label fx:id="lblTab1" text="Label" />
</children>
</StackPane>
</children>
</AnchorPane>
</content>
</Tab>
<Tab text="Untitled Tab 2">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TextField fx:id="tfTab2" layoutX="220.0" layoutY="86.0" />
<StackPane layoutX="195.0" layoutY="140.0" prefHeight="150.0" prefWidth="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<children>
<Label fx:id="lblTab2" text="Label" />
</children>
</StackPane>
</children>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
You have to create a new .fxml file for the Tab then set the fx:controller=TabController then you can <fx:include source="myTab.fxml">
So you can include this 3 times then you will have three tabs with the sam controller.
So the main .fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TabPane?>
<TabPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="TabPaneController">
<tabs>
<fx:include fx:id="FirstTab" source="CustomTab.fxml"/>
<fx:include fx:id="SecondTab" source="CustomTab.fxml"/>
<fx:include fx:id="ThirdTab" source="CustomTab.fxml"/>
</tabs>
</TabPane
>
And the child .fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Tab?>
<Tab xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="TabController">
<!--content-->
</Tab>
So now you have three tabs with the same Controller.
I have built a GUI using scene builder, through eclipse.
I am trying to run the MainApp class to view the GUI in eclipse, everything compiles, there are no error messages in the console, a java process opens but nothing actually happens and no window is created on screen.
I have been through oracle's site and attempted to alter the code but nothing works. I have updated java, reinstalled javafx etc in eclipse. I also tried the program throuhg netbeans to the same effect.
Running on MacOS X
package main;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class MainApp extends Application {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Application.launch(MainApp.class, (java.lang.String[])null);
}
#Override
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("GUI.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception ex) {
Logger.getLogger(MainApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
`package main;
The controller class
public class Controller implements Initializable {
#FXML
Button checkButton;
#FXML
Button callButton;
#FXML
Button raiseButton;
#FXML
Button foldButton;
public void buttonClicked() {
System.out.println("Button was clicked");
}
#Override
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
}
}
}
The FXML file
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.LineChart?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="800.0" style="-fx-background-color: #FFFFFF;" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.Controller">
<children>
<SplitPane dividerPositions="0.29949874686716793" layoutX="123.0" layoutY="67.0" prefHeight="433.0" prefWidth="800.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="67.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<LineChart layoutY="206.0" prefHeight="215.0" prefWidth="235.0">
<xAxis>
<CategoryAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</LineChart>
<LineChart prefHeight="215.0" prefWidth="235.0">
<xAxis>
<CategoryAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</LineChart>
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<SplitPane dividerPositions="0.6783216783216783" orientation="VERTICAL" prefHeight="498.0" prefWidth="555.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0" />
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="127.0" prefWidth="553.0">
<children>
<TextArea disable="true" layoutX="9.0" layoutY="23.0" prefHeight="106.0" prefWidth="536.0" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="9.0" AnchorPane.rightAnchor="8.0" AnchorPane.topAnchor="23.0" />
<Label layoutX="14.0" layoutY="6.0" text="Live guidance:" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
</items>
</SplitPane>
<ImageView fitHeight="62.0" fitWidth="200.0" layoutX="14.0" layoutY="5.0">
<image>
<Image url="#../../../../../Desktop/Dissertation%20files/logo.jpg" />
</image>
</ImageView>
<ButtonBar layoutX="456.0" layoutY="16.0" prefHeight="40.0" prefWidth="200.0">
<buttons>
<Button fx:id="checkButton" mnemonicParsing="false" onAction="#buttonClicked" onMouseClicked="#buttonClicked" style="-fx-background-radius: 10;" text="Check" />
<Button fx:id="callButon" mnemonicParsing="false" onAction="#buttonClicked" onMouseClicked="#buttonClicked" style="-fx-background-radius: 10;" text="Call" />
<Button fx:id="raiseButton" mnemonicParsing="false" onAction="#buttonClicked" onMouseClicked="#buttonClicked" prefHeight="27.0" prefWidth="81.0" style="-fx-background-radius: 10;" text="Raise" />
<Button fx:id="foldButton" mnemonicParsing="false" onAction="#buttonClicked" onMouseClicked="#buttonClicked" style="-fx-background-radius: 10;" text="Fold" />
</buttons>
</ButtonBar>
</children>
</AnchorPane>
Apologies if I am missing something simple.
If the classes and the fxml file is under same package then the loader line should be like this
Parent root = FXMLLoader.load(getClass().getResource("/package_name/fxml2GUI.fxml"));
Put your source's package name in the place of "packagename"
I try to display my "main.fxml" file into TapPane which connect with my other .fxml file. But unfortunately throw exception. What is wrong?
It is controller of tabs.fxml :
Tabs class
package View;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class Tabs implements Initializable {
#FXML
TabPane tabPane = null;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
try {
tabPane.getTabs().addAll((Tab) FXMLLoader.load(this.getClass().getResource("main.fxml")));
} catch (IOException e) {
e.printStackTrace();
}
}
}
tabs.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane
maxHeight="-Infinity"
maxWidth="-Infinity"
minHeight="-Infinity"
minWidth="-Infinity"
prefHeight="400.0"
prefWidth="600.0"
xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="View.Tabs">
<children>
<TabPane
fx:id="tabPane"
prefHeight="400.0"
prefWidth="600.0"
tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab text="Untitled Tab 1" >
<content>
</content>
</Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
It is main.fxml. It contain a form and a button. I try to display this form in my "tab.fxml" through Tab class
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane
id="main"
maxHeight="-Infinity"
maxWidth="-Infinity"
minHeight="-Infinity"
minWidth="-Infinity"
prefHeight="400.0"
prefWidth="600.0"
xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="View.Chat">
<children>
<AnchorPane
minHeight="0.0"
minWidth="0.0"
prefHeight="180.0"
prefWidth="200.0" />
<TextArea
fx:id="text"
layoutX="14.0"
layoutY="317.0"
prefHeight="69.0"
prefWidth="435.0" />
<TextArea
fx:id="chatField"
editable="false"
layoutX="14.0"
layoutY="14.0"
prefHeight="289.0"
prefWidth="435.0" />
<Button
fx:id="send"
layoutX="486.0"
layoutY="334.0"
mnemonicParsing="false"
onAction="#sendMessage"
prefHeight="30.0
prefWidth="66.0"
text="Send" />
</children>
</AnchorPane>
But throw the exception:
javafx.scene.layout.AnchorPane cannot be cast to
javafx.scene.control.Tab
/E:/JavaFXTest/out/production/JavaFXTest/View/tabs.fxml
at View.Tabs.initialize(Tabs.java:21)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2193)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2069)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2830)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2809)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2795)
The error message tells you the problem:
javafx.scene.layout.AnchorPane cannot be cast to
javafx.scene.control.Tab
The root element of your tab.fxml file is an AnchorPane, but you are trying to treat it as a Tab:
(Tab) FXMLLoader.load(this.getClass().getResource("main.fxml"))
You can either change the FXML file so the root element is a tab:
<Tab xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="View.Chat">
<AnchorPane> id="main" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" >
<children>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
<TextArea fx:id="text" layoutX="14.0" layoutY="317.0" prefHeight="69.0" prefWidth="435.0" />
<TextArea fx:id="chatField" editable="false" layoutX="14.0" layoutY="14.0" prefHeight="289.0" prefWidth="435.0" />
<Button fx:id="send" layoutX="486.0" layoutY="334.0" mnemonicParsing="false" onAction="#sendMessage" prefHeight="30.0" prefWidth="66.0" text="Send" />
</children>
</AnchorPane>
</Tab>
or
you can create the Tab in Java code in the controller:
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
try {
Tab tab = new Tab();
tabPane.getTabs().add(tab);
tab.setContent((Node) FXMLLoader.load(this.getClass().getResource("main.fxml")));
} catch (IOException e) {
e.printStackTrace();
}
}
I just facing a problem to realize a full MVC model with JavaFX.
I created an easy structure in an fxml file with a split pane.
The idea is to have on the left side a tree menu and on the left side GUI elements to configure my GUI settings.
To fill up the right side I wanted to load corresponding fxml files in the pane.
Triggered via mouseclickevents which are realized in the Tree Items.
The problem is, I have no Idea what functions I have to use in the controller.java file to load an fxml file and to make it in visible in the right side of the split pane.
EDIT:
Here is my code:
Thats the FXML MainFrame:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?language javascript?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="MenuItems.Menu_Item_Controller">
<children>
<SplitPane dividerPositions="0.2593984962406015" layoutY="-7.0" prefHeight="600.0" prefWidth="800.0" AnchorPane.bottomAnchor="7.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="-7.0">
<items>
<AnchorPane fx:id="Preferences_Left" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<TreeView fx:id="Preference_Tree" layoutY="23.0" prefHeight="575.0" prefWidth="204.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="23.0">
<root>
<TreeItem value="Case Full Name">
<children>
<TreeItem value="Test1">
<children>
<TreeItem>
<value>
<Label fx:id="XML_Center_Fields" onMouseClicked="#XML_Center_Fields" prefWidth="180" text="Test" />
</value>
</TreeItem>
<TreeItem>
<value>
<CheckBox id="checkBox2" prefWidth="180.0" text="TWO" />
</value>
</TreeItem>
<TreeItem>
<value>
<CheckBox id="checkBox3" prefWidth="180.0" text="THREE" />
</value>
</TreeItem>
</children>
</TreeItem>
</children>
</TreeItem>
</root>
</TreeView>
</children>
</AnchorPane>
<AnchorPane fx:id="Preferences_Right" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<AnchorPane fx:id="XML_Center_Field" layoutX="64.0" layoutY="23.0" prefHeight="575.0" prefWidth="588.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="23.0">
</AnchorPane>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
That's the FXML I want to call:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="218.0" prefWidth="239.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Button layoutX="130.0" layoutY="122.0" mnemonicParsing="false" text="Button" />
</children>
</AnchorPane>
And that's the controller File which uses an action from the first FXML to call the other with goal to visualize it at the right side of the split-pane.
package MenuItems;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.JavaFXBuilderFactory;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.control.TreeView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
/**
* Created by tkeller2 on 25.11.2014.
*/
public class Menu_Item_Controller extends Pane {
public AnchorPane Preferences_Left;
public TreeView Preference_Tree;
public AnchorPane Preferences_Right;
public AnchorPane XML_Center_Field;
TitledPane titledPane = new TitledPane();
public void XML_Center_Fields(Event event) throws Exception {
final FXMLLoader fxmlLoader = new FXMLLoader( getClass().getResource( "Test.fxml"));
fxmlLoader.setRoot(XML_Center_Field);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch( IOException exception) {
throw new RuntimeException( exception);
}
getChildren().add(XML_Center_Field
);
}
}
I know it is not working. The error-message is clear:
Caused by: javafx.fxml.LoadException: Root value already specified.
But I haven't any clue. Suggestions?
thanks for the answer. I am sure it points in the right direction, but I couldn't get it running.
Please have a look to my code.
Thats the FXML MainFrame:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?language javascript?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="MenuItems.Menu_Item_Controller">
<children>
<SplitPane dividerPositions="0.2593984962406015" layoutY="-7.0" prefHeight="600.0" prefWidth="800.0" AnchorPane.bottomAnchor="7.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="-7.0">
<items>
<AnchorPane fx:id="Preferences_Left" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<TreeView fx:id="Preference_Tree" layoutY="23.0" prefHeight="575.0" prefWidth="204.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="23.0">
<root>
<TreeItem value="Case Full Name">
<children>
<TreeItem value="Test1">
<children>
<TreeItem>
<value>
<Label fx:id="XML_Center_Fields" onMouseClicked="#XML_Center_Fields" prefWidth="180" text="Test" />
</value>
</TreeItem>
<TreeItem>
<value>
<CheckBox id="checkBox2" prefWidth="180.0" text="TWO" />
</value>
</TreeItem>
<TreeItem>
<value>
<CheckBox id="checkBox3" prefWidth="180.0" text="THREE" />
</value>
</TreeItem>
</children>
</TreeItem>
</children>
</TreeItem>
</root>
</TreeView>
</children>
</AnchorPane>
<AnchorPane fx:id="Preferences_Right" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<AnchorPane fx:id="XML_Center_Field" layoutX="64.0" layoutY="23.0" prefHeight="575.0" prefWidth="588.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="23.0">
</AnchorPane>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
That's the FXML I want to call:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="218.0" prefWidth="239.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Button layoutX="130.0" layoutY="122.0" mnemonicParsing="false" text="Button" />
</children>
</AnchorPane>
And that's the controller File which uses an action from the first FXML to call the other with goal to visualize it at the right side of the split-pane.
package MenuItems;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.JavaFXBuilderFactory;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.control.TreeView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
/**
* Created by tkeller2 on 25.11.2014.
*/
public class Menu_Item_Controller extends Pane {
public AnchorPane Preferences_Left;
public TreeView Preference_Tree;
public AnchorPane Preferences_Right;
public AnchorPane XML_Center_Field;
TitledPane titledPane = new TitledPane();
public void XML_Center_Fields(Event event) throws Exception {
final FXMLLoader fxmlLoader = new FXMLLoader( getClass().getResource( "Test.fxml"));
fxmlLoader.setRoot(XML_Center_Field);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch( IOException exception) {
throw new RuntimeException( exception);
}
getChildren().add(XML_Center_Field
);
}
}
I know it is not working. The error-message is clear:
Caused by: javafx.fxml.LoadException: Root value already specified.
But I haven't any clue. Suggestions?
I do it like this:
public class Task extends Pane {
TitledPane titledPane;
public Task() {
final FXMLLoader fxmlLoader = new FXMLLoader( getClass().getResource( "Task.fxml"));
titledPane = new TitledPane();
fxmlLoader.setRoot( titledPane);
fxmlLoader.setController( this);
try {
fxmlLoader.load();
} catch( IOException exception) {
throw new RuntimeException( exception);
}
getChildren().add( titledPane);
}
...
}
Task is just a custom TitledPane object that's created via fxml. I put several of these Task objects on a scene.
I'm not sure if this is the currently proper way for JavaFX 8, but it works.