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.
Related
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.
I am working on simple application which I need to make executable.
I am trying to switch from one scene to another in same window. Everything work perfectly when running in Intellij. However, when I created executable app suddenly control buttons stopped working.
There is my main class:
package code;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("FxmlLoginMenu.fxml"));
primaryStage.setTitle("Quiz application");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Controller Class:
One method inside which is executed when button pressed
package code;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import java.io.IOException;
public class Controller {
#FXML public Button signUp;
#FXML public void signUp() throws IOException {
Parent tableViewParent = FXMLLoader.load(getClass().getResource("FXMLRegister.fxml"));
Scene tableViewScene = new Scene(tableViewParent);
Stage window = (Stage) signUp.getScene().getWindow();
window.setScene(tableViewScene);
window.show();
}
}
And the last FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.effect.InnerShadow?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Line?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane fx:controller="code.Controller" prefHeight="385.0" prefWidth="437.0" xmlns="http://javafx.com/javafx/9.0.4" xmlns:fx="http://javafx.com/fxml/1" >
<children >
<MenuBar />
<AnchorPane id="login" maxHeight="-1.0" maxWidth="-1.0" prefHeight="418.0" prefWidth="626.0" style="-fx-background-color: #74AFAD#74AFAD;" VBox.vgrow="ALWAYS">
<children>
<AnchorPane id="login2" layoutX="325.0" layoutY="40.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="291.0" prefWidth="313.0" style="-fx-background-color: #D9853B#D9853B;">
<children>
<TextField fx:id="loginField" alignment="TOP_CENTER" layoutX="75.0" layoutY="95.0" promptText="Login">
<effect>
<InnerShadow />
</effect>
</TextField>
<PasswordField fx:id="passwordField" alignment="TOP_CENTER" layoutX="75.0" layoutY="159.0" promptText="Password">
<effect>
<InnerShadow blurType="TWO_PASS_BOX" />
</effect>
</PasswordField>
<Button fx:id="loginButton" layoutX="177.0" layoutY="247.0" mnemonicParsing="false" prefHeight="27.0" prefWidth="65.0" style="-fx-background-color: #74AFAD#74AFAD #74AFAD#74AFAD;" text="Login" />
<Button fx:id="signUp" onAction="#signUp" layoutX="75.0" layoutY="247.0" mnemonicParsing="false" style="-fx-background-color: #74AFAD#74AFAD #74AFAD#74AFAD;" text="Sign up" />
<Button fx:id="signUpAdmin" layoutX="242.0" layoutY="8.0" mnemonicParsing="false" style="-fx-background-color: #74AFAD#74AFAD #74AFAD#74AFAD;" text="Admin" />
</children>
</AnchorPane>
<Line endX="100.0" fill="#ff2323" layoutX="360.0" layoutY="190.0" rotate="90.0" startX="-190.0" stroke="#e43030" strokeLineJoin="ROUND" strokeMiterLimit="0.0" />
<Text fill="#d9853b" layoutX="21.0" layoutY="202.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Welcome to Quiz app" wrappingWidth="284.21875">
<font>
<Font size="27.0" />
</font>
</Text>
</children>
</AnchorPane>
<AnchorPane />
</children>
</AnchorPane>
Ok, I managed to fix that.
The problem was in the Controller class. It tried to load FXML with
FXMLLoader.load(getClass().getResource("FXMLRegister.fxml"));
where it should be
FXMLLoader.load(getClass().getResource("FxmlRegister.fxml"));
Apparently IntelliJ did not catch that error so it was working while running by IntelliJ.
I'm adding tabs dynamically from fxml files by clicking a button. Is there a way to check to see if that tab is already opened in TabPane in JavaFX and switch to that Tab instead of adding the same Tab to TabPane.
Here is my controller class:-
package application;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.AnchorPane;
public class MainController implements Initializable{
#FXML
public TabPane myTabPane ;
public AnchorPane myAnchorPane;
#FXML
public Button btnTab1 = new Button();
#FXML
public Button btnTab2 = new Button();
#FXML
public Button btnTab3 = new Button();
#Override
public void initialize(URL location, ResourceBundle resources) {
btnTab1.setOnAction(e -> {
//System.out.println("Clicked");
try {
Tab myNewTab = FXMLLoader.load(this.getClass().getResource("MyTestTab.fxml"));
myTabPane.getTabs().add(myNewTab);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
});
btnTab2.setOnAction(e -> {
try {
Tab myNewTab = FXMLLoader.load(this.getClass().getResource("MyTestTab2.fxml"));
myTabPane.getTabs().add(myNewTab);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
});
}
}
Here is my Main FXML File:-
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
<top>
<ToolBar prefHeight="40.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<items>
<Button fx:id="btnTab1" mnemonicParsing="false" text="Tab1" />
<Button fx:id="btnTab2" mnemonicParsing="false" text="Tab2" />
<Button fx:id="btnTab3" mnemonicParsing="false" text="Tab3" />
</items>
</ToolBar>
</top>
<center>
<SplitPane dividerPositions="0.29797979797979796" prefHeight="160.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<items>
<AnchorPane fx:id="myTabAnchPane" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<TabPane fx:id="myTabPane" layoutX="-12.0" layoutY="34.0" prefHeight="358.0" prefWidth="175.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children></AnchorPane>
<AnchorPane fx:id="myAnchorPane" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
</items>
</SplitPane>
</center>
</BorderPane>
And here is my FXML File for one of the Tab (Tab2):-
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<Tab fx:id="tab2" text="My Profile" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
<content>
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<HBox spacing="10.0">
<children>
<Label text="Bank Statement File" />
<TextField prefHeight="25.0" prefWidth="288.0" />
<Button mnemonicParsing="false" text="Browse" />
</children>
<VBox.margin>
<Insets left="20.0" top="20.0" />
</VBox.margin>
</HBox>
<HBox VBox.vgrow="ALWAYS">
<children>
<Pane prefHeight="200.0" prefWidth="135.0" />
<TextArea HBox.hgrow="ALWAYS" />
<Pane prefHeight="200.0" prefWidth="200.0" />
</children>
<padding>
<Insets top="50.0" />
</padding>
</HBox>
<Pane prefHeight="64.0" prefWidth="600.0" />
</children>
</VBox>
</content></Tab>
Just have the controller track which FXML files you have opened (I refactored the code slightly to get rid of all the repetition).
As an aside, never, ever initialize #FXML-annotated fields. I.e. never do #FXML private Button btnTab1 = new Button();.
package application;
import java.io.IOException;
import java.net.URL;
import java.util.Map ;
import java.util.HashMap ;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.AnchorPane;
public class MainController implements Initializable{
private Map<String, Tab> openTabs = new HashMap<>();
#FXML
private TabPane myTabPane ;
#FXML
private AnchorPane myAnchorPane;
#FXML
private Button btnTab1 ;
#FXML
private Button btnTab2 ;
#FXML
private Button btnTab3 ;
#Override
public void initialize(URL location, ResourceBundle resources) {
btnTab1.setOnAction(e -> openTab("MyTestTab.fxml"));
btnTab2.setOnAction(e -> openTab("MyTestTab2.fxml"));
}
private void openTab(String fxmlFile) {
if (openTabs.containsKey(fxmlFile)) {
myTabPane.getSelectionModel().select(openTabs.get(fxmlFile));
} else {
try {
Tab myNewTab = FXMLLoader.load(this.getClass().getResource(fxmlFile));
myTabPane.getTabs().add(myNewTab);
openTabs.put(fxmlFile, myNewTab);
myNewTab.setOnClosed(e -> openTabs.remove(fxmlFile));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
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();
}
}