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);
}
}
Related
I'm building a program with JavaFX and I have an Accordion ac injected #FXML and I have a button that creates a titled pane in the Accordion. The problem is that this button on click adds a titled pane to the accordion once.
I'm using this code:
t1.setContent(l);
ac.getPanes().add(t1);
I want to add one pane every click on this button. Please help me and thank you!
is this what you are looking for?
Scene.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="404.0" prefWidth="543.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="pl.brocode.tg.magisterka.mavenproject1.FXMLController">
<children>
<Button fx:id="button" layoutX="193.0" layoutY="283.0" onAction="#handleButtonAction" text="Click Me!" AnchorPane.bottomAnchor="1.0" AnchorPane.leftAnchor="193.0" AnchorPane.rightAnchor="193.0" />
<ScrollPane fitToHeight="true" fitToWidth="true" prefViewportHeight="160.0" prefViewportWidth="320.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content>
<Accordion fx:id="accordion" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</content>
</ScrollPane>
</children>
</AnchorPane>
FXMLController
package test;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Accordion;
import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.AnchorPane;
public class FXMLController implements Initializable {
#FXML
private Accordion accordion;
#FXML
private void handleButtonAction(ActionEvent event) {
AnchorPane newPanelContent = new AnchorPane();
newPanelContent.getChildren().add(new Label("Hello World"));
TitledPane pane = new TitledPane("World Pane", newPanelContent);
System.out.println(accordion);
accordion.getPanes().add(pane);
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
every time you click a button, new panel is added. if you wane do something with that panel in the future, you can assign it to field (list), or get it from accordion via getChildren() method.
an edit has been made to a code, for better display of added panes
Can Anybody tell me how to construct HiddenSidesPane in FXML not in the controller?
I am having the basic controller code for this but I am not able to understand how to create fxml structure from that.
Can I have something like this? Below code;
<HiddenSidesPane prefWidth="800.0" pinnedSide="TOP">
<content>
<HBox fillHeight="false" nodeOrientation="RIGHT_TO_LEFT"
prefHeight="27.0" prefWidth="800.0" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="3.0" StackPane.alignment="TOP_RIGHT">
<children>
<Label prefHeight="14.0" prefWidth="94.0" text="Value Date From">
<HBox.margin>
<Insets right="2.0" top="5.0" />
</HBox.margin>
</Label>
</children>
<StackPane.margin>
<Insets top="2.0" />
</StackPane.margin>
</HBox>
</content>
</HiddenSidesPane>
This how I made a fast example with the offical FXSampler of ControlsFX in mind:
Assumptions
You already set up your FXML Project and added the ControlsFX.jar as dependency on your build path.
FXMLDocument.fxml
Watch for the import statements.
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.*?>
<?import org.controlsfx.control.*?>
<StackPane xmlns:fx="http://javafx.com/fxml/1" prefHeight="200" prefWidth="320" fx:controller="javafxapplication17.FXMLDocumentController">
<children>
<HiddenSidesPane fx:id="pane">
<content>
<Label alignment="CENTER" style="-fx-background-color: white; -fx-border-color: black;" maxHeight="1000.0" maxWidth="1000.0" text="Content Node" />
</content>
<top>
<Label fx:id="pinLabel" style="-fx-background-color: rgba(0,255,0,.25);" text="(Click to pin / unpin)" alignment="CENTER" prefHeight="50.0" prefWidth="50.0" onMouseClicked="#handleMouseClicked" />
</top>
</HiddenSidesPane>
</children>
</StackPane>
FXMLController.java
Inject your variables pane and pinLabel to set them.
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Side;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import org.controlsfx.control.HiddenSidesPane;
public class FXMLDocumentController implements Initializable {
#FXML
private HiddenSidesPane pane;
#FXML
private Label pinLabel;
#FXML
private void handleMouseClicked(MouseEvent event) {
if (pane.getPinnedSide() != null) {
pinLabel.setText("(unpinned)");
pane.setPinnedSide(null);
} else {
pinLabel.setText("(pinned)");
pane.setPinnedSide(Side.TOP);
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
JavaFXApplication17.java
Sorry for that name :-)
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class JavaFXApplication17 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);
}
}
As far as you already know here is the JavaDoc of HiddenSidesPane: http://controlsfx.bitbucket.org/org/controlsfx/control/HiddenSidesPane.html
And if you need an example download the Zip http://fxexperience.com/downloads/controlsfx-8.40.9.zip and unzip it, there is a file controlsfx-samples-8.40.9.jar inside. Double click it and show the sources.
I've been trying button events between 2 scenes in Javafx.
This is Start.fxml (in view package):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="292.0" prefWidth="383.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="controller.StartController">
<children>
<Label fx:id="lbl1" layoutX="87.0" layoutY="60.0" prefHeight="17.0" prefWidth="209.0" />
<TextField fx:id="txt1" layoutX="87.0" layoutY="121.0" prefHeight="25.0" prefWidth="209.0" />
<Button fx:id="btn1" layoutX="171.0" layoutY="191.0" mnemonicParsing="false" onAction="#btn1Click" text="Click" />
</children>
</AnchorPane>
This is Preserences.fxml (in view package):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="292.0" prefWidth="383.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="controller.PreferencesController">
<children>
<Label fx:id="lbl2" layoutX="87.0" layoutY="60.0" prefHeight="17.0" prefWidth="209.0" />
<TextField fx:id="txt2" layoutX="87.0" layoutY="121.0" prefHeight="25.0" prefWidth="209.0" />
<Button fx:id="btn2" layoutX="171.0" layoutY="191.0" mnemonicParsing="false" onAction="#btn2Click" text="Click" />
</children>
</AnchorPane>
This is Main.fxml which is like a container for the previous 2 files.(in view package):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="481.0" prefWidth="468.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="controller.MainController">
<children>
<TabPane layoutX="14.0" layoutY="14.0" prefHeight="481.0" prefWidth="468.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<tabs>
<Tab closable="false" text="Start">
<content>
<fx:include source="Start.fxml" />
</content>
</Tab>
<Tab closable="false" text="Preferences">
<content>
<fx:include source="Preferences.fxml" />
</content>
</Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
This is StartController.java (in controller package):
package controller;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
public class StartController implements Initializable {
#FXML public static Label lbl1;
#FXML public static TextField txt1;
#FXML public static Button btn1;
#Override
public void initialize(URL location, ResourceBundle resources) {
}
#FXML private void btn1Click(ActionEvent e){
System.out.println("Button 1 clicked");
lbl1.setText(PreferencesController.txt2.getText());
}
}
This is PreferencesController.java (in controller package):
package controller;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
public class PreferencesController implements Initializable {
#FXML public static Label lbl2;
#FXML public static TextField txt2;
#FXML public static Button btn2;
#Override
public void initialize(URL location, ResourceBundle resources) {
}
#FXML private void btn2Click(ActionEvent e){
System.out.println("Button 2 clicked");
lbl2.setText(StartController.txt1.getText());
}
}
This is MainController.java (in controller package):
package controller;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.Initializable;
public class MainController implements Initializable{
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
}
}
Finally, this is Main.java in application package:
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("/view/Main.fxml"));
Scene scene = new Scene(root);
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);
}
}
But when I clicked the buttons, it gives me the errors:
"Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException...
...
Caused by: java.lang.NullPointerException
at controller.StartController.btn1Click(StartController.java:26)
... 61 more"
Please help me! :(
OK so the NPE is being thrown on this line:
lbl1.setText(PreferencesController.txt2.getText());
At the basic Java level, are only two ways that you could get that to happen:
when lnl1 is null, or
when PreferencesController.txt2 is null.
No other explanations are possible ... given that PreferencesController.txt2 is a static field.
I'm not familiar with JavaFX or FXML, but I suspect that your mistake is declaring the fields as static. I suspect that this causes the FXML mechanisms to not inject the reference to the UI component correctly. So those variables remain as null ... and you get an NPE.
Confirmation is here: https://stackoverflow.com/a/23109125/139985. (Thanks for the link #James_D)
Ok so I've created my own customer label, for this example it's extremely basic. What I did was extend the Javafx Label in my custom class called MyLabel. I'm also using FXML to create the GUI. Now when I do this I can't seem to instantiate with my custom class as I get this error.
"Can not set net.blacksquirreldevs.tests.MyLabel field net.blacksquirreldevs.tests.SampleLabelController.sampleLabel to javafx.scene.control.Label"
Here is the code for everything
Main.java
package net.blacksquirreldevs.tests;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("SampleLabel");
AnchorPane anchorPane = (AnchorPane) FXMLLoader.load(getClass().getResource("SampleLabel.fxml"));
primaryStage.setScene(new Scene(anchorPane));
primaryStage.show();
}
public static void main(String... args) {
launch(args);
}
}
MyLabel.java
package net.blacksquirreldevs.tests;
import javafx.scene.control.Label;
public class MyLabel extends Label {
public MyLabel(String text) {
super();
setText(text);
}
}
SampleLabelController.java
package net.blacksquirreldevs.tests;
import javafx.fxml.FXML;
import java.net.URL;
import java.util.ResourceBundle;
public class SampleLabelController {
#FXML
private ResourceBundle resources;
#FXML
private URL location;
#FXML
private MyLabel sampleLabel = new MyLabel("Hello world!");
#FXML
void initialize() {
assert sampleLabel != null : "fx:id=\"sampleLabel\" was not injected: check your FXML file 'SampleLabel.fxml'.";
}
}
And finally the fxml file SampleLabel.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" fx:controller="net.blacksquirreldevs.tests.SampleLabelController">
<children>
<Label fx:id="sampleLabel" layoutX="153.0" layoutY="171.0" text="Sample Text">
<font>
<Font name="Arial Bold" size="50.0" />
</font>
</Label>
</children>
</AnchorPane>
So what I want to know is why I can' declare, in my SamplelabelController class, the sampleLabel as MyLabel?
Hopefully I've explained this well enough, if not let me know and I'll try to go a bit more in detail.
You are using <Label ... in your FXML instead of <MyLabel
Beside that your MyLabel has a none default constructor and in this case you NEED to provide a builder named MyLabelBuilder so that FXMLLoader can create an instance of MyLabel
Is it possible to define the TabBar to place the tabs at bottom instead of top?
To set the side of the tabs use following snippet:
TabPane tabPane = new TabPane();
Tab tab1 = new Tab("Tab 1");
tab1.setContent(new Label("Tab1 content"))
tabPane.getTabs().add(tab1);
tabPane.setSide(Side.BOTTOM)
Now the content is above the tabs.
Also as full FXML example:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.collections.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.web.*?>
<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="example.MainViewController">
<bottom>
<HBox>
<children>
<Button fx:id="btnNewTab" mnemonicParsing="false" text="Add New Tab" onAction="#btnNewTabAction" />
</children>
</HBox>
</bottom>
<center>
<TabPane fx:id="tabPane" side="BOTTOM">
<tabs>
<Tab text="Untitled Tab 1">
<content>
<AnchorPane id="Content">
<Label>Content 1</Label>
</AnchorPane>
</content>
</Tab>
<Tab text="Untitled Tab 2">
<content>
<AnchorPane id="Content">
<Label>Content 2</Label>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
</center>
<top>
<Label text="TabPane Example" />
</top>
</BorderPane>
The main class:
package example;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.fxml.JavaFXBuilderFactory;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class ExampleMain extends Application {
/**
* #param args
*/
public static void main(String[] args) {
Application.launch(ExampleMain.class, args);
}
#Override
public void start(Stage primaryStage) throws Exception {
URL location = ExampleMain.class.getResource("MainView.fxml");
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(location);
fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
try {
Parent root = (Parent) fxmlLoader.load(location.openStream());
// in case you need access to the controller
MainViewController mainViewController = fxmlLoader.getController();
primaryStage.setScene(new Scene(root, 1024, 768));
Scene s = primaryStage.getScene();
s.setRoot(root);
primaryStage.sizeToScene();
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And the controller:
package example;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
public class MainViewController {
private static int counter = 0;
#FXML
private TabPane tabPane;
#FXML
public void btnNewTabAction() {
Tab tab = new Tab();
tab.setText("new Tab " + ++counter);
tab.setContent(new Label("Content of new tab " + counter));
tabPane.getTabs().add(tab);
}
}
as you can see in the example, fxml is an xml representation of the Java classes. If the class has an property side (getSide, setSide) then the class has in fxml an attribute side. So you can read the api documentation to find out which attributes are available in fxml as well.
Hope this helps.
Don't define the TabBar! Use a proper layout pane e.g. javafx.scene.layout.BorderPane.
Find attached examples for JavaFX 2.0 API and FXML:
JAVAFX 2.0 API
package tabtest;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TabTest extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
Scene scene = new Scene(root, 300, 250);
TabPane tabPane = new TabPane();
Tab tab1 = new Tab("Tab 1");
tabPane.getTabs().add(tab1);
root.setBottom(tabPane);
primaryStage.setScene(scene);
primaryStage.show();
}
}
For further information have a look at http://download.oracle.com/javafx/2.0/layout/jfxpub-layout.htm
FXML
package fxmltest;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class FxmlTest extends Application {
public static void main(String[] args) {
Application.launch(FxmlTest.class, args);
}
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));
Scene scene = new Scene(root, 300, 250);
stage.setScene(scene);
stage.show();
}
}
Sample.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane>
<bottom>
<TabPane>
<tabs>
<Tab text="Tab 1" />
</tabs>
</TabPane>
</bottom>
</BorderPane>