JavaFX loading a new fxml file into the same scene - javafx

I have a class named Test1Controller where a Scene is executed and in another class, Test2Controller, I want to load another FXML but in the same Scene. Can someone help me with this?
public class Test1Controller {
private static AnchorPane page;
public static Stage initialicePage() {
primaryStage = new Stage();
page = (AnchorPane) FXMLLoader.load(Principal.class.getResource("Test1.fxml"));
Scene scene = new Scene(page);
primaryStage.setScene(scene);
primaryStage.setTitle("Test1");
primaryStage.setResizable(true);
primaryStage.setMinHeight(700);
primaryStage.setMinWidth(824);
primaryStage.setMaximized(true);
primaryStage.show();
}
}

public class SwitchScene 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();
}
public static void main(String[] args) {
launch(args);
}
}
public class FXMLDocumentController {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
try {
Parent root = FXMLLoader.load(getClass().getResource("SecondScreen.fxml"));
Scene dashboard=new Scene(root);
//This line gets the Stage Information
Stage window=(Stage)((Node)event.getSource()).getScene().getWindow();
window.setScene(dashboard);
window.show();
} catch (IOException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class SecondScreenController {
public void MoveBack(ActionEvent event){
try {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene dashboard = new Scene(root);
//This line gets the Stage Information
//here we get the stage from event action and setting the root element in the scene and display scene with stage object (window) which is retrieved from action event
Stage window=(Stage)((Node)event.getSource()).getScene().getWindow();
window.setScene(dashboard);
window.show();
} catch (IOException ex) {
Logger.getLogger(SecondScreenController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//FXMLDocument.xml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="switchscene.FXMLDocumentController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>
////SecondScreen fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="switchscene.SecondScreenController">
<children>
<Button fx:id="btnMove" layoutX="269.0" layoutY="188.0" mnemonicParsing="false" onAction="#MoveBack" text="Move Back" />
</children>
</AnchorPane>

Related

JavaFx: multiple controllers

I'm working on the project which contains multiple controllers (1 main and two for each of the Fxml files). Unfortunately while running the program, console throw the NullPointerExeption at me. I found out that it's the main controller fault, but still having this information I'm unable to fix this. Could you give me some tips how to solve this issue ?
Here i got the full track:
MainController class:
public class MainController {
#FXML LogInController logInController;
DBConnect dbConnect;
#FXML FlightControlController flightControlController;
#FXML public void initialize() {
logInController.initialize(this);
flightControlController.initialize(this);
dbConnect.initialize(this);
}
}
DBConnect class:
public void dbConnect() throws SQLException {
try {
Conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/nasa", "root", "1234");
} catch(Exception e) {
System.out.println(e.getStackTrace());
}
}
public boolean isCorrect(String login,String password) throws SQLException, IOException {
Stmt = Conn.createStatement();
Rs = Stmt.executeQuery("SELECT * FROM Users WHERE login='"+login+"'AND password='"+password+"';");
if(Rs.next()) {
return true;
} else {
return false;
}
}
public void initialize(MainController mainController) {
this.mainController=mainController;
}
LogInController class:
MainController mainController;
#FXML DBConnect dbConnect;
#FXML TextField logginField = null;
#FXML PasswordField passwordFiled=null;
#FXML Button logInButton;
#FXML
public void buttonClicked(ActionEvent event) throws SQLException, IOException {
mainController.dbConnect.dbConnect();
if(mainController.dbConnect.isCorrect(logginField.getText(),passwordFiled.getText())) {
Parent root = FXMLLoader.load(getClass().getResource("/view/FlightControlView.fxml"));
Scene scene = new Scene(root);
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
stage.setScene(scene);
stage.show();
} else {
System.out.print("An error have occured");
}
}
public void initialize(MainController mainController) {
this.mainController=mainController;
}
FlightControlController Class:
#FXML Label label;
MainController mainController;
public void initialize(MainController mainController) {
this.mainController = mainController;
}
And the error which occurs:
Caused by: java.lang.NullPointerException at
controller.LogInController.buttonClicked(LogInController.java:31) ...
62 more
I'm not sure but is it possible that MainController (which doesn't have his own Fxml file) so that FXMLLoader doesn't initialize MainController's properties?
#EDIT
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="693.0" prefWidth="1062.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.LogInController">
<children>
<SplitPane dividerPositions="0.21320754716981133" layoutX="331.0" layoutY="220.0" prefHeight="693.0" prefWidth="1062.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="160.0" prefWidth="100.0">
<children>
<Label alignment="CENTER" layoutY="-1.0" maxHeight="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="70.0" prefWidth="222.0" text="NASA DATABASE" />
<TextField fx:id="logginField" layoutX="18.0" layoutY="101.0" promptText="Login" />
<PasswordField fx:id="passwordFiled" layoutX="18.0" layoutY="165.0" promptText="Password" />
<Button fx:id="logInButton" onAction="#buttonClicked" layoutX="79.0" layoutY="230.0" mnemonicParsing="false" text="Log In" />
</children>
</AnchorPane>
<AnchorPane prefHeight="691.0" prefWidth="493.0" SplitPane.resizableWithParent="false">
<children>
<Label alignment="CENTER" layoutX="97.0" layoutY="104.0" prefHeight="417.0" prefWidth="635.0" text="NOT AVAILABLE, PLEASE LOG IN" AnchorPane.leftAnchor="113.0" AnchorPane.rightAnchor="113.0">
<font>
<Font name="System Bold Italic" size="37.0" />
</font>
</Label>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>

JAVAFX - Change specific Pane only using 1 window

Can you Help me how to change the Spesific pane in 1 scene.
So when i want to click the Menu A. The Content will change to content A.
And when i click the menu B. The Content will be change to Content B
i try with the 2 FXML and using normal method like load screen A an screen B
But the result only change the window. i want to change the content with 1 window only.
Is there any suggestion how to change the specific pane in 1 window?
As an option.
Make FXML and controller for any "Content" and when the some button is clicked to delete the old "Content" and upload new.
Working example below (edited according to James_D comment):
Main.java
public class Main extends Application {
Parent root;
Stage stage;
#Override
public void start(Stage primaryStage) {
try {
root = FXMLLoader.load(getClass().getResource("Main.fxml"));
stage = primaryStage;
stage.setTitle("Stage");
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<BorderPane fx:id="mainPane" 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="application.Controller">
<left>
<ToolBar orientation="VERTICAL" BorderPane.alignment="CENTER">
<items>
<Button mnemonicParsing="false" onAction="#onBtnAClick" text="A" />
<Button mnemonicParsing="false" onAction="#onBtnBClick" text="B" />
<Button mnemonicParsing="false" onAction="#onBtnCClick" text="C" />
</items>
</ToolBar>
</left>
</BorderPane>
Controller.java
import javafx.fxml.FXML;
import javafx.scene.layout.BorderPane;
public class Controller {
#FXML
BorderPane mainPane;
#FXML
public void onBtnAClick(){
ContentA contentA = new ContentA();
mainPane.setCenter(contentA);
}
#FXML
public void onBtnBClick(){
ContentB contentB = new ContentB();
mainPane.setCenter(contentB);
}
#FXML
public void onBtnCClick(){
ContentC contentC = new ContentC();
mainPane.setCenter(contentC);
}
}
And some sample of Content:
ContentA.java
public class ContentA extends AnchorPane{
public ContentA(){
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("ContentA.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ContentA.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<fx:root prefHeight="200.0" prefWidth="300.0" type="AnchorPane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<ListView layoutX="50.0" layoutY="-26.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</fx:root>
try to use this, its easy
Parent root = null;
try {
root=FXMLLoader.load(getClass().getResource("your_FXML_File.fxml"));
} catch (Exception e) {
}
borderpane.setCenter(root);

Copy entite fxml data to different container

I am having two vbox(es).
First vbox fx:id is vbox1
Second vbox fx:id is vbox2
In vbox1 I am having textbox, combobox, buttons and everything else.
I am having one button which want to copy(onclick) entire source/fxml from vbox1 to vbox2.
Is there anyway to do that?
Define the content of the VBoxes in a separate FXML file. You can include the content in the first VBox directly in your "main" fxml with a <fx:include>:
<VBox fx:id="vbox1">
<fx:include source="Content.fxml"/>
</VBox>
and then you can load another copy in the button's handler with
#FXML
public void handleButtonAction(ActionEvent e) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("Content.fxml"));
vbox2.getChildren().add(loader.load());
}
Complete example (everything in a package called application):
Main.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Button?>
<BorderPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
<center>
<HBox spacing="5">
<VBox fx:id="vbox1">
<fx:include source="Content.fxml"/>
</VBox>
<VBox fx:id="vbox2"/>
</HBox>
</center>
<bottom>
<Button text="Load" onAction="#load" BorderPane.alignment="CENTER"/>
</bottom>
</BorderPane>
MainController.java:
package application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.VBox;
public class MainController {
#FXML
private VBox vbox1 ;
#FXML
private VBox vbox2 ;
#FXML
private void load() throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("Content.fxml"));
vbox2.getChildren().add(loader.load());
}
}
Content.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.collections.FXCollections?>
<?import java.lang.String?>
<?import javafx.scene.control.Button?>
<VBox xmlns:fx="http://javafx.com/fxml/1">
<TextField promptText="Text Field"/>
<ComboBox>
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="One"/>
<String fx:value="Two"/>
<String fx:value="Three"/>
</FXCollections>
</items>
</ComboBox>
<Button text="Click me"/>
</VBox>
Main.java:
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("Main.fxml"));
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}

How customize a tooltip with css?

I am using the version javafx 2 with kepler and I tried to customized a tooltip without succeed:
.tooltip{
-fx-background-color: linear-gradient(blue,lightskyblue);
-fx-background-radius: 5;
}
.page-corner {
-fx-shape: " ";
}
It is not working. Do you have any ideas ?
Update:
here an mcve :
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class MainApp extends Application {
#Override
public void start(Stage stage) {
AnchorPane root;
try {
root = FXMLLoader.load(getClass().getResource("Sample.fxml"));
Scene scene = new Scene(root, 600, 400);
stage.setTitle("FXML Welcome");
stage.setScene(scene);
stage.show();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
Application.launch(MainApp.class, args);
}
}
Sample.fxml file :
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.image.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" stylesheets="MCVE/application.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Sample">
<children>
<TextField layoutX="66.0" layoutY="49.0">
<tooltip>
<Tooltip text="tooltip message" />
</tooltip>
</TextField>
</children>
</AnchorPane>
controller :
public class Sample {
//controller
}
application.css file :
.tooltip{
-fx-background-color: linear-gradient(blue,lightskyblue);
-fx-background-radius: 5.0;
}
.page-corner {
-fx-shape: " ";
}
I think this is because the Tooltip appears in its own window (Tooltip is a subclass of PopupControl, which eventually is a subclass of Window). Because you have applied the stylesheet to the AnchorPane, it isn't seen by the Tooltip, which is outside that hierarchy.
Instead, add the stylesheet to the Scene in your MainApp class:
scene.getStylesheets().add(getClass().getResource("/mcve/application.css").toExternalForm());

javafx and scene builder

#Override
public void start(Stage stage) throws Exception {
PieChart pie = new PieChart();
pie.setData(getChart());
StackPane pane = new StackPane();
Scene scene = new Scene(pane);
stage.setScene(scene);
pane.getChildren().addAll(pie);
stage.show();
}
private ObservableList<PieChart.Data> getChart() {
ObservableList<PieChart.Data> list = FXCollections.observableArrayList();
list.addAll(new PieChart.Data("java",20), new PieChart.Data("c",20),
new PieChart.Data("C++",20));
return list;
}
i want this chart to be displayed on scene builder. how is it possible..??
In SceneBuilder, from the menu:
Select File | Open
Choose pie.fxml
Select View | Show Sample Data
pie.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.chart.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<StackPane id="StackPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="250.0" prefWidth="300.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
<children>
<PieChart id="PieChart" prefHeight="-1.0" prefWidth="-1.0" />
</children>
</StackPane>

Resources