JavaFx 2.0 with FXML: tabs at bottom instead of top? - javafx

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>

Related

Share the same reusable FXML component in multiple views

I have a FXML view that contains a TabView with multiple tabs.
Every Tab has it's own FXML component + controller.
I would like all tabs to report progress via a component defined defined in the main view.
I know that I can inject child controllers into the main controller via FXML.
But to my current understanding, I need to access the parent controller inside my child controllers since the component is located in the main view.
I can also access the child controllers inside the initialize method of my main view. If I follow this path, I would need to modify the child controllers to set the shared component.
This is suboptimal, since the child components would be dependent on a main view that is performing those changes.
I created a MWE to illustrate the dilemma.
The question in short:
How can I report progress of Service1 and Service2 to the progressAndStatusGrid in the main view?
Callenge in short:
Make this application not throw a NPE and report progress to the progress component ;)
MWE:
Launcher:
package org.example;
public class Launcher {
public static void main(final String[] args) {
SimpleApplication.main(args);
}
}
Application:
package org.example;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class SimpleApplication extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/MainView.fxml"));
#SuppressWarnings("unused")
MainViewController controller = fxmlLoader.getController();
final Parent root = fxmlLoader.load();
final Scene scene = new Scene(root);
primaryStage.setTitle("Hello World");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
MainController:
package org.example;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.GridPane;
import java.net.URL;
import java.util.ResourceBundle;
public class MainViewController implements Initializable {
#FXML
GridPane progressAndStatusGrid;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
}
MainView:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane prefHeight="150.0" prefWidth="350.0" xmlns="http://javafx.com/javafx/17.0.2-ea"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.MainViewController">
<padding>
<Insets top="4" right="4" bottom="4" left="4"/>
</padding>
<top>
</top>
<center>
<TabPane>
<Tab text="tab1" closable="false">
<fx:include fx:id="tab1" source="Tab1View.fxml"/>
</Tab>
<Tab text="tab2" closable="false">
<fx:include fx:id="tab2" source="Tab2View.fxml"/>
</Tab>
</TabPane>
</center>
<bottom>
<fx:include fx:id="progressAndStatusGrid"
source="ProgressAndStatusGridComponent.fxml"/>
</bottom>
</BorderPane>
"Shared" componentController:
package org.example;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.HBox;
import java.net.URL;
import java.util.ResourceBundle;
public class ProgressAndStatusGridComponentController implements Initializable {
#FXML
ProgressBar progressBar;
#FXML
HBox progressStatusBox;
#FXML
Label progressLabel;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
}
"Shared" componentView:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.layout.*?>
<GridPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="org.example.ProgressAndStatusGridComponentController"
hgap="4" vgap="4">
<padding>
<Insets top="4" right="4" bottom="4" left="4"/>
</padding>
<fx:define>
<ColumnConstraints fx:id="colConstraints2" percentWidth="100"/>
</fx:define>
<columnConstraints>
<fx:reference source="colConstraints2"/>
<fx:reference source="colConstraints2"/>
</columnConstraints>
<ProgressBar fx:id="progressBar" GridPane.columnIndex="0" GridPane.rowIndex="0"/>
<HBox fx:id="progressStatusBox" alignment="CENTER" spacing="4" GridPane.columnIndex="1" GridPane.rowIndex="0">
<padding>
<Insets top="4" right="4" bottom="4" left="4"/>
</padding>
<Label fx:id="progressLabel"/>
</HBox>
</GridPane>
Tab1Controller:
package org.example;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import java.net.URL;
import java.util.ResourceBundle;
public class Tab1Controller implements Initializable {
#FXML
Button button1;
Service1 service1 = new Service1();
// How to get a reference, that is already initialized?
#FXML
ProgressAndStatusGridComponentController progressAndStatusGridComponentController;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
button1.disableProperty().bind(service1.runningProperty());
}
public void handleButtonClick(ActionEvent actionEvent) {
service1.cancel();
service1.reset();
progressAndStatusGridComponentController.progressBar.progressProperty().bind(service1.progressProperty());
progressAndStatusGridComponentController.progressLabel.textProperty().bind(service1.messageProperty());
service1.start();
}
}
Tab1View:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="org.example.Tab1Controller">
<center>
<Button fx:id="button1" text="Start Background Progress #1" onAction="#handleButtonClick"/>
</center>
</BorderPane>
Tab2Controller:
package org.example;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import java.net.URL;
import java.util.ResourceBundle;
public class Tab2Controller implements Initializable {
#FXML
Button button2;
Service2 service2 = new Service2();
// How to get a reference, that is already initialized?
#FXML
ProgressAndStatusGridComponentController progressAndStatusGridComponentController;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
button2.disableProperty().bind(service2.runningProperty());
}
public void handleButtonClick(ActionEvent actionEvent) {
service2.cancel();
service2.reset();
progressAndStatusGridComponentController.progressBar.progressProperty().bind(service2.progressProperty());
progressAndStatusGridComponentController.progressLabel.textProperty().bind(service2.messageProperty());
service2.start();
}
}
Tab2View:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="org.example.Tab2Controller">
<center>
<Button fx:id="button2" text="Start Background Progress #2" onAction="#handleButtonClick"/>
</center>
</BorderPane>
Service1:
package org.example;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
public class Service1 extends Service<Void> {
static final int workLoad = 100;
#Override
protected Task<Void> createTask() {
return new Task<>() {
#Override
protected Void call() throws Exception {
updateMessage("Starting Task #1..");
for (int i = 0; i < workLoad; i++) {
Thread.sleep(200);
updateProgress(i, workLoad);
updateMessage(i + " elements done");
}
updateMessage("Task #1 done!");
return null;
}
};
}
}
Service2:
package org.example;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
public class Service2 extends Service<Void> {
static final int workLoad = 100;
#Override
protected Task<Void> createTask() {
return new Task<>() {
#Override
protected Void call() throws Exception {
updateMessage("Starting Task #2..");
for (int i = 0; i < workLoad; i++) {
Thread.sleep(200);
updateProgress(i, workLoad);
updateMessage(i + " elements done");
}
updateMessage("Task #2 done!");
return null;
}
};
}
}

JavaFx ImageView won't resize on fitWidthProperty bind to VBox

I am trying to re-size an image so it fits (scaled) in the space allotted by a SplitPane (for workaround suggestions: this image will change when running the program, it should be generated from the text). The ImageView I'm using currently changes the location of the SplitPane Divider. The divider can never cause the ImageView to decrease past the size of the image.
Two images showing this behavior.
Linking the ImageView fitWidthProperty to a VBox has not given me the resize behavior I expected. Increasing the ImageView's size does work (where it is fixed without the binding), but the image never grows, it just gets borders around it.
My MWE:
sample.fxml:
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<SplitPane orientation="HORIZONTAL" xmlns:fx="http://javafx.com/fxml">
<TextArea fx:id="textArea"/>
<VBox fx:id="vBox" alignment="CENTER">
<HBox fx:id="hBox" alignment="CENTER">
<ImageView fx:id="imageView"/>
</HBox>
</VBox>
</SplitPane>
Controller.java:
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
public class Controller {
#FXML
private TextArea textArea = new TextArea();
#FXML
private VBox vBox = new VBox();
#FXML
private HBox hBox = new HBox();
#FXML
private ImageView imageView = new ImageView();
public Controller() {
imageView.fitWidthProperty().bind(vBox.widthProperty());
imageView.fitHeightProperty().bind(hBox.heightProperty());
}
public void start() {
textArea.setText("text");
Image image = new Image("https://www.google.nl/images/srpr/logo11w.png");
imageView.setImage(image);
}
}
and Main.java:
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(final Stage primaryStage) throws Exception {
final Controller controller = new Controller();
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("sample.fxml"));
fxmlLoader.setController(controller);
final Parent root = fxmlLoader.load();
primaryStage.setTitle("MWE");
final Scene scene = new Scene(root, 640, 480);
primaryStage.setScene(scene);
primaryStage.show();
controller.start();
}
public static void main(String[] args) {
launch(args);
}
}
You can try binding the ImageView's fitWidthProperty() to the SplitPane's divider position property.
A binding similar to this should work :
imageView.fitWidthProperty().bind(Bindings.subtract(1,
splitPane.getDividers().get(0).positionProperty())
.multiply(splitPane.widthProperty());
this is my sample for you!
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<StackPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center">
<SplitPane fx:id="splitpane">
<VBox fx:id="left" prefWidth="300" prefHeight="200" style="-fx-background-color: antiquewhite">
<ImageView fx:id="image1" preserveRatio="true" pickOnBounds="true">
<image>
<Image url="#/sample/test.jpg"/>
</image>
</ImageView>
</VBox>
<VBox fx:id="right" prefWidth="300" prefHeight="300" style="-fx-background-color: aquamarine">
<ImageView fx:id="image2" preserveRatio="true" pickOnBounds="true">
<image>
<Image url="#/sample/test.jpg"/>
</image>
</ImageView>
</VBox>
</SplitPane>
package sample;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.SplitPane;
import javafx.scene.image.ImageView;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable {
#FXML
ImageView image1;
#FXML
ImageView image2;
#FXML
SplitPane splitpane;
#Override
public void initialize(URL location, ResourceBundle resources) {
splitpane.getDividers().get(0).positionProperty().addListener((observable, oldValue, newValue) -> {
System.out.println(newValue);
int w = 600;
double w1 = w * newValue.doubleValue();
double w2 = w - w1;
image1.setFitWidth(w1);
image2.setFitWidth(w2);
});
}
}

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);
}
}

Show / Hide a Node within a stage

I am aware that there are already answers for this question but somehow, it was not able to solve my problem.
When I click the textfield in IMAGE1, I want the keyboard FXML(IMAGE2) to appear as is in IMAGE3. But the thing is, I can't seem to find the solution. How do I do this?
I need your help please.
IMAGE1
IMAGE2
IMAGE3
I am experimenting with something similar, here is what I came up with (one of many possible solutions):
You need to wrap your main layout (IMAGE1) in a StackPane. Its usage is to overlay what needs be overlaid (the keyboard in your case). The keyboard is placed in another pane (a VBox in the following example). The VBox:
is placed in the StackPane after the main layout to sit on top of it
is given a maximum height, so that it doesn't fill the entire window
is given a translateY equal to the height
and bottom alignment
The relevant code n FXML:
<VBox fx:id="statusContainer" maxHeight="100.0" prefHeight="100.0"
translateY="100.0" StackPane.alignment="BOTTOM_LEFT" />
This will always be outside of the view. Toggling the keyboard requires 2 TranslateTransitions (can it be done with 1, I wonder?), one to move the keyboard up, one down.
The example code:
1) Java:
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Test1 extends Application
{
#FXML private VBox statusContainer;
private TranslateTransition showStatus;
private TranslateTransition hideStatus;
boolean showsStatus = false;
#Override
public void start(Stage primaryStage) {
try {
StackPane page = (StackPane) FXMLLoader.load(this.getClass().getResource("test1.fxml"));
Scene scene = new Scene(page);
primaryStage.setTitle(this.getClass().getName());
primaryStage.setScene(scene);
primaryStage.sizeToScene();
primaryStage.show();
}
catch (IOException e) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, e);
}
}
#FXML void initialize() {
showStatus = new TranslateTransition(Duration.millis(250), statusContainer);
showStatus.setByY(-100.0);
showStatus.setOnFinished(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
showsStatus = true;
}
});
hideStatus = new TranslateTransition(Duration.millis(250), statusContainer);
hideStatus.setByY(100.0);
hideStatus.setOnFinished(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
showsStatus = false;
}
});
}
public void toggleStatus() {
if( showsStatus ) {
showStatus.stop();
hideStatus.play();
}
else {
hideStatus.stop();
showStatus.play();
}
}
public static void main(String[] args) {
launch(args);
}
}
2) FXML (call it test1.fxml to match the code):
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<StackPane id="StackPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" fx:controller="fancymsg.FancyMsg1">
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Button mnemonicParsing="false" onAction="#toggleStatus" text="Status" AnchorPane.leftAnchor="50.0" AnchorPane.topAnchor="100.0" />
</children>
</AnchorPane>
<VBox fx:id="statusContainer" maxHeight="100.0" prefHeight="100.0" translateY="100.0" StackPane.alignment="BOTTOM_LEFT" />
</children>
<stylesheets>
<URL value="#test1.css" />
</stylesheets>
</StackPane>
3) The CSS for the VBox to stand out (call it test1.css):
#statusContainer {
-fx-background-color: -fx-color;
}
An mcve version of this answer
can be found here

Using custom javafx label doesn't work

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

Resources