I'm Creating a loading screen for my application which has complex Neumorphism Design using InnerShadow, although CPU and RAM usage is less, the application causes lagging effect for animation like Circular Progress Indicator of Gluon charm-glisten.jar as well as PathTransition animation. In this loading screen you can see a red rectangle moving around the design and the progress indicator in blue color in the innermost layer
Java Code:
package application;
import java.net.URL;
import java.util.*;
import com.gluonhq.charm.glisten.control.ProgressIndicator;
import javafx.animation.*;
import javafx.animation.PathTransition.*;
import javafx.application.*;
import javafx.concurrent.*;
import javafx.event.*;
import javafx.fxml.*;
import javafx.stage.*;
import javafx.util.*;
import javafx.scene.*;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
public class Main extends Application implements Initializable
{
private double xOffset = 0;
private double yOffset = 0;
#FXML
ProgressIndicator pg1;
static AnchorPane root;
private PathTransition pathTransitionCircle;
public void start(Stage primaryStage)
{
try
{
primaryStage.initStyle(StageStyle.TRANSPARENT);
root = FXMLLoader.load(getClass().getResource("Test1.fxml"));
Scene scene = new Scene(root,600,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
scene.setFill(javafx.scene.paint.Color.TRANSPARENT);
primaryStage.setScene(scene);
primaryStage.show();
root.setOnMousePressed(new EventHandler<MouseEvent>()
{
public void handle(MouseEvent e)
{
xOffset = e.getSceneX();
yOffset = e.getSceneY();
}
});
root.setOnMouseDragged(new EventHandler<MouseEvent>()
{
public void handle(MouseEvent e)
{
primaryStage.setX(e.getScreenX() - xOffset);
primaryStage.setY(e.getScreenY() - yOffset);
}
});
Rectangle rect2 = new Rectangle(0, 0, 20, 20);
rect2.setArcHeight(10);
rect2.setArcWidth(10);
rect2.setFill(Color.RED);
root.getChildren().add(rect2);
Path path2 = createEllipsePath(400, 200, 150, 150, 0);
path2.setLayoutX(57);
path2.setLayoutY(10);
root.getChildren().add(path2);
pathTransitionCircle = new PathTransition();
pathTransitionCircle.setDuration(Duration.seconds(6));
pathTransitionCircle.setPath(path2);
pathTransitionCircle.setNode(rect2);
pathTransitionCircle.setOrientation(OrientationType.ORTHOGONAL_TO_TANGENT);
pathTransitionCircle.setCycleCount(PathTransition.INDEFINITE);
pathTransitionCircle.setInterpolator(Interpolator.LINEAR);
pathTransitionCircle.setAutoReverse(false);
pathTransitionCircle.play();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
launch(args);
}
#Override
public void initialize(URL arg0, ResourceBundle arg1)
{
Task<Void> task = new Task<Void>()
{
protected Void call() throws Exception
{
for (int i = 0; i <= 100; i++)
{
updateProgress(i, 100);
Thread.sleep(40);
}
//Platform.runLater(() -> primaryStage.close());
return null;
}
};
pg1.progressProperty().unbind();
pg1.progressProperty().bind(task.progressProperty());
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
task.setOnSucceeded(new EventHandler<WorkerStateEvent>()
{
public void handle(WorkerStateEvent arg0)
{
try
{
/*primaryStage.close();
primaryStage = null;
System.gc();
FXML_Loader f1 = new FXML_Loader();
f1.intermediate();*/
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
private Path createEllipsePath(double centerX, double centerY, double radiusX, double radiusY, double rotate)
{
ArcTo arcTo = new ArcTo();
arcTo.setX(centerX - radiusX + 1); // to simulate a full 360 degree celcius circle.
arcTo.setY(centerY - radiusY);
arcTo.setSweepFlag(false);
arcTo.setLargeArcFlag(true);
arcTo.setRadiusX(radiusX);
arcTo.setRadiusY(radiusY);
arcTo.setXAxisRotation(rotate);
Path path = new Path();
path.getElements().addAll(
new MoveTo(centerX - radiusX, centerY - radiusY),
arcTo,
new ClosePath()); // close 1 px gap.
path.setStroke(Color.BLUE);
path.getStrokeDashArray().setAll(5d, 5d);
return path;
}
}
FXML Code:
<?xml version="1.0" encoding="UTF-8"?>
<?import com.gluonhq.charm.glisten.control.ProgressIndicator?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.effect.InnerShadow?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: transparent;" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Main">
<children>
<VBox alignment="CENTER" layoutX="163.5" layoutY="63.5" prefHeight="290.0" prefWidth="290.0" style="-fx-background-color: #3D4956; -fx-background-radius: 150;">
<effect>
<InnerShadow color="#00000070" offsetX="-4.0" offsetY="-4.0">
<input>
<InnerShadow color="#a7a7a7bf" offsetX="4.0" offsetY="4.0" />
</input>
</InnerShadow>
</effect>
<children>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" style="-fx-background-color: #3D4956; -fx-background-radius: 150;" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
</VBox.margin>
<effect>
<InnerShadow color="#0000008c" offsetX="4.0" offsetY="4.0">
<input>
<InnerShadow color="#a6a6a65c" offsetX="-4.0" offsetY="-4.0" />
</input>
</InnerShadow>
</effect>
<children>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" style="-fx-background-color: #3D4956; -fx-background-radius: 150;" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
</VBox.margin>
<effect>
<InnerShadow color="#0000008c" offsetX="-4.0" offsetY="-4.0">
<input>
<InnerShadow color="#a6a6a65c" offsetX="4.0" offsetY="4.0" />
</input>
</InnerShadow>
</effect>
<children>
<VBox prefHeight="200.0" prefWidth="100.0" style="-fx-background-color: #3D4956; -fx-background-radius: 150;" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
</VBox.margin>
<effect>
<InnerShadow color="#0000008c" offsetX="4.0" offsetY="4.0">
<input>
<InnerShadow color="#a6a6a65c" />
</input>
</InnerShadow>
</effect>
<children>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" style="-fx-background-color: #3D4956; -fx-background-radius: 150;" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
</VBox.margin>
<effect>
<InnerShadow color="#0000008c" offsetX="-4.0" offsetY="-4.0">
<input>
<InnerShadow color="#a6a6a65c" offsetX="4.0" offsetY="4.0" />
</input>
</InnerShadow>
</effect>
<children>
<AnchorPane prefHeight="58.0" prefWidth="141.0" style="-fx-background-color: #3D4956; -fx-background-radius: 150;" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
</VBox.margin>
<effect>
<InnerShadow color="#0000008c" offsetX="4.0" offsetY="4.0">
<input>
<InnerShadow color="#a6a6a65c" offsetX="-4.0" offsetY="-4.0" />
</input>
</InnerShadow>
</effect>
<children>
<ImageView fitHeight="42.0" fitWidth="50.0" layoutX="49.0" layoutY="40.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#logo/database1.png" />
</image>
</ImageView>
<Label layoutX="57.0" layoutY="81.0" prefHeight="19.0" prefWidth="34.0" text="SQL" textFill="YELLOW">
<font>
<Font name="System Bold Italic" size="14.0" />
</font>
</Label>
<Label layoutX="38.0" layoutY="97.0" prefHeight="20.0" prefWidth="73.0" text="Developer" textFill="YELLOW">
<font>
<Font name="System Bold Italic" size="14.0" />
</font>
</Label>
<ProgressIndicator fx:id="pg1" layoutX="8.0" layoutY="7.0" prefHeight="108.0" prefWidth="122.0" progress="1.0" radius="60.0" />
</children>
</AnchorPane>
</children>
</VBox>
</children>
</VBox>
</children>
</VBox>
</children>
</VBox>
</children>
</VBox>
</children>
</AnchorPane>
Loading Screen Design
Related
Following is the fxml I am using for one of the Javafx forms:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane fx:id="CustomerAddLabel" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="683.0" prefWidth="824.0" style="-fx-background-color: aliceblue; -fx-border-color: black; -fx-border-radius: 5;" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="c195.View_Controller.CustomerScreenController">
<children>
<Label alignment="TOP_CENTER" layoutX="300.0" layoutY="14.0" prefHeight="38.0" prefWidth="226.0" style="-fx-border-color: gray; -fx-border-radius: 5;" text="Customer" textAlignment="CENTER">
<font>
<Font name="System Bold Italic" size="25.0" />
</font>
</Label>
<AnchorPane layoutX="16.0" layoutY="102.0" prefHeight="404.0" prefWidth="363.0" style="-fx-background-color: white;">
<children>
<TableView fx:id="CustomerTable" layoutY="1.0" style="-fx-border-color: black; -fx-border-radius: 5;">
<columns>
<TableColumn fx:id="CustomerIDColumn" prefWidth="63.0" text="ID" />
<TableColumn fx:id="CustomerNameColumn" prefWidth="175.0" text="Customer Name" />
<TableColumn fx:id="CustomerPhoneColumn" prefWidth="123.0" text="Phone" />
<TableColumn fx:id="CustomerAddressColumn" prefWidth="123.0" text="Address" />
<TableColumn fx:id="CustomerPostalCodeColumn" prefWidth="123.0" text="Postal Code" />
<TableColumn fx:id="CustomerDivisionColumn" prefWidth="123.0" text="Division" />
<TableColumn fx:id="CustomerCountryColumn" prefWidth="123.0" text="Country" />
</columns>
</TableView>
</children>
</AnchorPane>
<ButtonBar layoutX="587.0" layoutY="564.0" prefHeight="40.0" prefWidth="200.0">
</ButtonBar>
<ButtonBar layoutX="500.0" layoutY="613.0" prefHeight="40.0" prefWidth="200.0">
<buttons>
<Button fx:id="CustomerBackButton" mnemonicParsing="false" onAction="#CustomerBackButtonHandler" text="Back" />
<Button fx:id="CustomerDeleteButton" mnemonicParsing="false" onAction="#CustomerDeleteButtonHandler" text="Delete" />
</buttons>
</ButtonBar>
<Label fx:id="CustomerLabel" layoutX="542.0" layoutY="52.0" prefHeight="40.0" prefWidth="90.0" textFill="#1924e8">
<font>
<Font name="System Bold Italic" size="20.0" />
</font>
</Label>
</children>
</AnchorPane>
Following is a snippet of the corresponding controller:
public class CustomerScreenController implements Initializable {
#FXML
private TableView<Customer> CustomerTable;
#FXML
private TableColumn<Customer, String> CustomerIDColumn;
#FXML
private TableColumn<Customer, String> CustomerNameColumn;
#FXML
private TableColumn<Customer, String> CustomerPhoneColumn;
#FXML
private TableColumn<Customer, String> CustomerAddressColumn;
#FXML
private TableColumn<Customer, String> CustomerPostalCodeColumn;
#FXML
private TableColumn<Customer, String> CustomerDivisionColumn;
#FXML
private TableColumn<Customer, String> CustomerCountryColumn;
#FXML
private Button CustomerBackButton;
private Parent root;
private Stage stage;
private ObservableList<Customer> customerOL = FXCollections.observableArrayList();
#Override
public void initialize(URL url, ResourceBundle rb) {
PropertyValueFactory<Customer, String> custCustomerIDFactory = new PropertyValueFactory<>("customerID");
PropertyValueFactory<Customer, String> custNameFactory = new PropertyValueFactory<>("customerName");
PropertyValueFactory<Customer, String> custPhoneFactory = new PropertyValueFactory<>("phone"); //String value "CustomerPhone" calls getCustomerPhone method
PropertyValueFactory<Customer, String> custCountryFactory = new PropertyValueFactory<>("country");
PropertyValueFactory<Customer, String> custDivisionFactory = new PropertyValueFactory<>("division");
PropertyValueFactory<Customer, String> custAddressFactory = new PropertyValueFactory<>("address");
PropertyValueFactory<Customer, String> custPostalCodeFactory = new PropertyValueFactory<>("postalCode");
CustomerIDColumn.setCellValueFactory(custCustomerIDFactory);
CustomerNameColumn.setCellValueFactory(custNameFactory);
CustomerPhoneColumn.setCellValueFactory(custPhoneFactory);
CustomerCountryColumn.setCellValueFactory(custCountryFactory);
CustomerDivisionColumn.setCellValueFactory(custDivisionFactory);
CustomerAddressColumn.setCellValueFactory(custAddressFactory);
CustomerPostalCodeColumn.setCellValueFactory(custPostalCodeFactory);
try {
updateCustomerTableView();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
My UI is appearing like this:
This is appearing cropped. And the full column name Country is not visible. But if I resize it to maximum, then I do see the buttons. How can I make it scrollable? Both the full pane and the TableView inside it so that this issue doesn't appear on the screen.
It looks like you are using AnchorPane incorrectly. I would use VBox or BorderPane. This example uses VBox.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="683.0" prefWidth="824.0" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label alignment="CENTER" prefHeight="38.0" prefWidth="226.0" style="-fx-border-color: gray; -fx-border-radius: 5;" text="Customer" textAlignment="CENTER">
<font>
<Font name="System Bold Italic" size="25.0" />
</font>
<VBox.margin>
<Insets bottom="60.0" top="20.0" />
</VBox.margin>
</Label>
<TableView fx:id="CustomerTable" style="-fx-border-color: black; -fx-border-radius: 5;" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="CustomerIDColumn" prefWidth="63.0" text="ID" />
<TableColumn fx:id="CustomerNameColumn" prefWidth="175.0" text="Customer Name" />
<TableColumn fx:id="CustomerPhoneColumn" prefWidth="123.0" text="Phone" />
<TableColumn fx:id="CustomerAddressColumn" prefWidth="123.0" text="Address" />
<TableColumn fx:id="CustomerPostalCodeColumn" prefWidth="123.0" text="Postal Code" />
<TableColumn fx:id="CustomerDivisionColumn" prefWidth="123.0" text="Division" />
<TableColumn fx:id="CustomerCountryColumn" prefWidth="123.0" text="Country" />
</columns>
<VBox.margin>
<Insets left="10.0" right="10.0" />
</VBox.margin>
</TableView>
<ButtonBar>
<buttons>
<Button fx:id="CustomerBackButton" mnemonicParsing="false" onAction="#CustomerBackButtonHandler" text="Back" />
<Button fx:id="CustomerDeleteButton" mnemonicParsing="false" onAction="#CustomerDeleteButtonHandler" text="Delete" />
</buttons>
<VBox.margin>
<Insets bottom="20.0" right="20.0" top="20.0" />
</VBox.margin>
</ButtonBar>
</children>
</VBox>
I have created a Layout with FXML which consists of a BorderPane with a sideMenu and an innerBorderPane for other stuff...
But since I'm barely starting with FXML in JavaFX I just need to know how to do the next thing...
Custom.fxml (This is the main FXML layout)
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<VBox fx:controller="Transcoro.Controllers.TabManager" alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="442.0" prefWidth="338.0" spacing="5.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox prefHeight="59.0" prefWidth="124.0">
<children>
<VBox prefHeight="59.0" prefWidth="90.0" style="-fx-background-color: blue;" />
<VBox alignment="CENTER_LEFT" prefHeight="59.0" prefWidth="165.0">
<children>
<Label text="Bienvenido, Rodolfo">
<font>
<Font name="System Bold" size="15.0" />
</font>
</Label>
<Label text="Administrador" />
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
<HBox.margin>
<Insets />
</HBox.margin>
<padding>
<Insets left="10.0" />
</padding>
</VBox>
</children>
<VBox.margin>
<Insets bottom="15.0" />
</VBox.margin>
</HBox>
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Unidades" textAlignment="CENTER" textFill="#2491ff" />
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Empleados" textAlignment="CENTER" textFill="#2491ff" />
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Clientes" textAlignment="CENTER" textFill="#2491ff" />
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Viajes" textAlignment="CENTER" textFill="#2491ff" />
</children>
<padding>
<Insets top="20.0" />
</padding>
</VBox>
sideMenu.fxml (This is the sideMenu FXML layout)
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<fx:root type="javafx.scene.layout.VBox" alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="442.0" prefWidth="338.0" spacing="5.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox prefHeight="59.0" prefWidth="124.0">
<children>
<VBox prefHeight="59.0" prefWidth="90.0" style="-fx-background-color: blue;" />
<VBox alignment="CENTER_LEFT" prefHeight="59.0" prefWidth="165.0">
<children>
<Label text="Bienvenido, Rodolfo">
<font>
<Font name="System Bold" size="15.0" />
</font>
</Label>
<Label text="Administrador" />
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
<HBox.margin>
<Insets />
</HBox.margin>
<padding>
<Insets left="10.0" />
</padding>
</VBox>
</children>
<VBox.margin>
<Insets bottom="15.0" />
</VBox.margin>
</HBox>
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Unidades" textAlignment="CENTER" textFill="#2491ff" />
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Empleados" textAlignment="CENTER" textFill="#2491ff" />
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Clientes" textAlignment="CENTER" textFill="#2491ff" />
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" nodeOrientation="LEFT_TO_RIGHT" text="Viajes" textAlignment="CENTER" textFill="#2491ff" />
</children>
<padding>
<Insets top="20.0" />
</padding>
</fx:root>
TabManager.java (This is the sideMenu JavaFX controller)
package Transcoro.Controllers;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.VBox;
import java.io.IOException;
public class TabManager extends VBox {
public TabManager(){
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/resources/view/sideMenu.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
}
MainLayout.java (This is the mainLayout JavaFX Controller)
package Transcoro.Core;
import Transcoro.Controllers.TabManager;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.*;
import java.io.IOException;
public class MainLayout extends BorderPane {
#FXML
private VBox sideMenu;
#FXML
private BorderPane innerContent;
#FXML
private HBox upperMenu;
#FXML
private ScrollPane contentScroll;
#FXML
private VBox otherPane;
public MainLayout(){
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/resources/view/Custom.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
TabManager _tabs = new TabManager();
this.setSideMenu(_tabs);
}
What I want to do is the following:
I have two layouts, the base which is the main Layout and sideMenu layout in another FXML
When I instantiate the mainLayout in my root that works fine, then when I want to insert the TabManager (VBox) into sideMenu (VBox from FXML) it doesn't work... I'm doing this:
TabManager _tabs = new TabManager();
this.setSideMenu(_tabs);
The only way I have made it work is by adding:
this.setLeft(this.sideMenu);
OR
this.setLeft(_tabs);
Which I think it shouldn't work that why, because I'm already stating that sideMenu goes on the Left BorderPane side, any idea on how should I approach this?
Firstly, remove fx:controller="Transcoro.Controllers.TabManager" from Custom.fxml. The controller is MainLayout, which you will set via FXMLLoader.
Secondly, don't call fxmlLoader.setRoot(this); in MainLayout. You should instead retrieve the root node out from Custom.fxml, then add it to MainLayout, which itself is a BorderPane.
Parent root = fxmlLoader.getRoot();
this.setCenter(root);
This will put everything from Custom.fxml as the center child of MainLayout.
Thirdly, setLeft() is working because you are setting the TabManager instance (which is a VBox) as the left child of MainLayout. setSideMenu() (which is assumed as the setter of #FXML private VBox sideMenu does not work because sideMenu is just a reference injected into the controller. When you change this reference, it does not change the original layout.
I am in the process of creating a javafx desktop application. The problem I'm encountering is if I add a controller to my fxml files the controls dissapear somehow. The program uses a fade transition to switch between the fxml files
AnchorPane reorderLevels,purchaseorder,onlineSales,generalLedger
,cashBook,payments,departmentalTransfers
,purchaseInvoice
,productMantainance,
branchTransfers,stockMovement,invoiceRegistration,stockTake;
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#Override
public void initialize(URL url, ResourceBundle rb) {
//load all the fxml screens when the buttons are clicked
try {
//screens for the application
reorderLevels = FXMLLoader.load(getClass().getResource("ReorderLevels.fxml"));
purchaseorder = FXMLLoader.load(getClass().getResource("PurchaseOrder.fxml"));
onlineSales = FXMLLoader.load(getClass().getResource("OnlineSales.fxml"));
generalLedger = FXMLLoader.load(getClass().getResource("GeneralLedger.fxml"));
cashBook = FXMLLoader.load(getClass().getResource("CashBook.fxml"));
departmentalTransfers = FXMLLoader.load(getClass().getResource("DepartmentalTransfers.fxml"));
purchaseInvoice = FXMLLoader.load(getClass().getResource("PurchaseInvoice.fxml"));
productMantainance = FXMLLoader.load(getClass().getResource("ProductMantainance.fxml"));
branchTransfers = FXMLLoader.load(getClass().getResource("BranchTransfers.fxml"));
stockMovement = FXMLLoader.load(getClass().getResource("StockMovement.fxml"));
payments = FXMLLoader.load(getClass().getResource("Payments.fxml"));
invoiceRegistration = FXMLLoader.load(getClass().getResource("InvoiceRegistration.fxml"));
stockTake = FXMLLoader.load(getClass().getResource("StockTake.fxml"));
//set each and every individual node when the buttons are clicked
setNode(reorderLevels);
} catch (IOException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void setNode(Node node) {
holderPane.getChildren().clear();
holderPane.getChildren().add((Node) node);
//the transition between the screens
FadeTransition ft = new FadeTransition(Duration.millis(1));
ft.setNode(node);
ft.setFromValue(0.1);
ft.setToValue(1);
ft.setCycleCount(1);
ft.setAutoReverse(false);
ft.play();
}
/* screens */
#FXML
private void switchReorderLevels(ActionEvent event) {
setNode(reorderLevels);
}
#FXML
private void switchOnlineSales(ActionEvent event) {
setNode(onlineSales);
}
#FXML
private void switchGeneralLedger(ActionEvent event) {
setNode(generalLedger);
}
#FXML
private void switchPurchaseOrder(ActionEvent event) {
setNode(purchaseorder);
}
#FXML
private void switchCashBook(ActionEvent event) {
setNode(cashBook);
}
#FXML
private void switchAlert(ActionEvent event) {
setNode(purchaseorder);
}
#FXML
private void switchPayments(ActionEvent event) {
setNode(payments);
}
#FXML
private void switchDepartmentalTransfers(ActionEvent event) {
setNode(departmentalTransfers);
}
#FXML
private void switchPurchaseInvoice(ActionEvent event) {
setNode(purchaseInvoice);
}
#FXML
private void switchProductMantainance(ActionEvent event) {
setNode(productMantainance);
}
#FXML
private void switchBranchTransfers(ActionEvent event) {
setNode(branchTransfers);
}
//this is a screen that will displayone of the layouts that will show re order levels
<AnchorPane id="AnchorPane" prefHeight="713.0" prefWidth="1219.0" style="-fx-background-color: white;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label layoutX="24.0" layoutY="17.0" prefHeight="30.0" prefWidth="285.0" style="-fx-font-size: 20; -fx-font-weight: bold; -fx-text-fill: #7387A8;" text="ReOrder Levels" />
<Separator layoutX="25.0" layoutY="54.0" prefHeight="5.0" prefWidth="1191.0" />
<Pane fx:id="tbl_reorderLevels" layoutX="25.0" layoutY="108.0" prefHeight="413.0" prefWidth="1174.0" style="-fx-background-color: #EFEFEF;">
<children>
<JFXComboBox fx:id="cmd_reOrder_productCode" layoutX="48.0" layoutY="33.0" prefHeight="25.0" prefWidth="267.0" promptText="Product Code" />
<JFXTextField fx:id="txt_reOrder_reorderLevel" labelFloat="true" layoutX="48.0" layoutY="91.0" prefHeight="25.0" prefWidth="267.0" promptText="Reorder Level" />
//this is the root layout that has buttons that will navigate between the screens using a fade transition
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXButton?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.effect.InnerShadow?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<!-- root layout -->
<AnchorPane id="AnchorPane" nodeOrientation="LEFT_TO_RIGHT" prefHeight="623.0" prefWidth="1271.0" style="-fx-background-color: #fff;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller = "dashboard.FXMLDocumentController">
<children>
<Pane layoutX="-2.0" prefHeight="81.0" prefWidth="1272.0" style="-fx-background-color: #0b8dee;" styleClass="head-background" stylesheets="#style.css" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label fx:id="labelEstock" layoutX="204.0" layoutY="-3.0" prefHeight="88.0" prefWidth="536.0" style="-fx-shape: round;" stylesheets="#custom.css" text="Oasys Estock" textFill="WHITE">
<font>
<Font name="Brush Script MT Italic" size="36.0" />
</font>
</Label>
<!-- <ImageView fx:id="imageEstock" fitHeight="110.0" fitWidth="92.0" layoutX="102.0" layoutY="8.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image
url="#../../../../AndroidStudioProjects/OasysEstock/app/src/main/res/drawable/fortified_icon.png" />
</image>
</ImageView> -->
</children>
</Pane>
<VBox layoutY="85.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="518.0" prefWidth="122.0" style="-fx-background-color: #0b8dee; -fx-background-radius: 15;">
<children>
<JFXButton id="btnReorderLevels" fx:id="btnReorderLevels" buttonType="RAISED" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onAction="#switchReorderLevels" prefHeight="47.0" prefWidth="107.0" style="-fx-background-radius: 100;" text="ReOrder Levels" textFill="#f5f0f0">
<VBox.margin>
<Insets />
</VBox.margin>
<font>
<Font name="Calibri" size="12.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnInvoiceRegistration" onAction="#switchInvoiceRegistration" prefHeight="25.0" prefWidth="121.0" text="Invoice Registration" textFill="#f8f4f4" />
<JFXButton fx:id="btnPurchaseOrder" buttonType="RAISED" onAction="#switchPurchaseOrder" prefHeight="34.0" prefWidth="107.0" text="Purchase Order" textFill="#f5f0f0">
<font>
<Font name="Cambria" size="12.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnOnlineSales" onAction="#switchOnlineSales" prefHeight="39.0" prefWidth="107.0" text="Online Sales" textFill="#fff9f9">
<font>
<Font name="Calibri" size="12.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnGeneralLedger" onAction="#switchGeneralLedger" prefHeight="40.0" prefWidth="108.0" text="General Ledger" textFill="#f2eeee" />
<JFXButton fx:id="btnCashBook" onAction="#switchCashBook" prefHeight="35.0" prefWidth="104.0" text="Cash Book" textFill="#fffefe" />
<JFXButton fx:id="btnPayments" buttonType="RAISED" onAction="#switchPayments" prefHeight="25.0" prefWidth="114.0" text="Payments" textFill="#fcf6f6" />
<JFXButton fx:id="btnDepartmentalTransfers" buttonType="RAISED" layoutX="10.0" layoutY="205.0" onAction="#switchDepartmentalTransfers" prefHeight="25.0" prefWidth="114.0" text="Dept Transfers" textFill="#fcf6f6" />
<JFXButton fx:id="btnProductMantainance" buttonType="RAISED" layoutX="10.0" layoutY="230.0" onAction="#switchProductMantainance" prefHeight="56.0" prefWidth="121.0" text="Product Mantainance" textFill="#fcf6f6">
<font>
<Font size="11.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnPurchaseInvoice" buttonType="RAISED" layoutX="10.0" layoutY="255.0" onAction="#switchPurchaseInvoice" prefHeight="56.0" prefWidth="121.0" text="Purchase Invoice" textFill="#fcf6f6">
<font>
<Font size="11.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnBranchTransfers" buttonType="RAISED" layoutX="10.0" layoutY="311.0" onAction="#switchBranchTransfers" prefHeight="56.0" prefWidth="121.0" text="Branch Transfers" textFill="#fcf6f6">
<font>
<Font size="11.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnStockMovement" buttonType="RAISED" layoutX="10.0" layoutY="367.0" onAction="#switchStockMovement" prefHeight="56.0" prefWidth="121.0" text="Stock Movement" textFill="#fcf6f6">
<font>
<Font size="11.0" />
</font>
</JFXButton>
<JFXButton fx:id="btnStockTake" buttonType="RAISED" layoutX="10.0" layoutY="448.0" onAction="#switchStockTake" prefHeight="56.0" prefWidth="121.0" text="Stock Take" textFill="#fcf6f6">
<font>
<Font size="11.0" />
</font>
</JFXButton>
</children>
<effect>
<InnerShadow blurType="TWO_PASS_BOX" choke="0.58" color="#212122" height="26.69" radius="10.620000000000001" width="17.79" />
</effect>
</VBox>
<AnchorPane fx:id="holderPane" layoutX="125.0" layoutY="96.0" prefHeight="507.0" prefWidth="1134.0"/>
</children>
</AnchorPane>
JavaFX: How to center an ImageView in a Pane
Hi,
I am trying to center and resize an ImageView according to the current Window size.
If I am putting the ImageView into a Pane, I cannot Center it.
If I am putting it into a StackPane instead, resizing of the Image doesn't work.
Any idea, what I am doing wrong?
Google couldn't help me.
Extract of FXML with Pane
<HBox prefHeight="100.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
<children>
<Button maxWidth="-Infinity" minWidth="-Infinity" mnemonicParsing="false" prefHeight="2000.0" prefWidth="100.0" text="Button" HBox.hgrow="ALWAYS" />
<Pane fx:id="paneMainImage" prefHeight="200.0" prefWidth="200.0" HBox.hgrow="ALWAYS">
<children>
<ImageView fx:id="imageMainImage" fitHeight="10.0" fitWidth="10.0" pickOnBounds="true" preserveRatio="true" />
</children>
<HBox.margin>
<Insets />
</HBox.margin>
</Pane>
<Button maxWidth="-Infinity" minWidth="-Infinity" mnemonicParsing="false" prefHeight="2000.0" prefWidth="100.0" text="Button" HBox.hgrow="ALWAYS" />
</children>
</HBox>
And here the Java code
public class FXMLDocumentController implements Initializable {
#FXML
Pane paneMainImage;
#FXML
ImageView imageMainImage;
#Override
public void initialize(URL url, ResourceBundle rb) {
Image i = new Image(getClass().getResource("resources/DSC_0168.JPG").toString());
paneMainImage.getWidth();
paneMainImage.getHeight();
imageMainImage.setImage(i);
imageMainImage.fitWidthProperty().bind(paneMainImage.widthProperty());
imageMainImage.fitHeightProperty().bind(paneMainImage.heightProperty());
}
}
Similar code with StackPane
<HBox prefHeight="100.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
<children>
<Button maxWidth="-Infinity" minWidth="-Infinity" mnemonicParsing="false" prefHeight="2000.0" prefWidth="100.0" text="Button" HBox.hgrow="ALWAYS" />
<StackPane fx:id="paneMainImage" prefHeight="150.0" prefWidth="200.0" HBox.hgrow="ALWAYS">
<children>
<ImageView fx:id="imageMainImage" fitHeight="10.0" fitWidth="10.0" pickOnBounds="true" preserveRatio="true" />
</children>
</StackPane>
<Button maxWidth="-Infinity" minWidth="-Infinity" mnemonicParsing="false" prefHeight="2000.0" prefWidth="100.0" text="Button" HBox.hgrow="ALWAYS" />
</children>
</HBox>
Java
public class FXMLDocumentController implements Initializable {
#FXML
StackPane paneMainImage;
#FXML
ImageView imageMainImage;
#Override
public void initialize(URL url, ResourceBundle rb) {
Image i = new Image(getClass().getResource("resources/DSC_0168.JPG").toString());
paneMainImage.getWidth();
paneMainImage.getHeight();
imageMainImage.setImage(i);
imageMainImage.fitWidthProperty().bind(paneMainImage.widthProperty());
imageMainImage.fitHeightProperty().bind(paneMainImage.heightProperty());
}
}
There is a similar discussion on another post. Have you tried using any of the solutions discussed there (in order of complexity)?
Using a BorderPane as a parent of the image to center it Using the
setX and setY methods to explicitly set the location of the image
So I have this code here:
// import statements are ommitted
public class HomePage implements Initializable{
#FXML
private volatile MenuButton fullUserName;
public void initialize(URL url, ResourceBundle resourceBundle)
{
}
public void loadHomePage(Stage primaryStage) throws IOException {
Parent HomePage = FXMLLoader.load(LoginScreen.class.getResource("HomePage.fxml"));
Timer animTimer = new Timer();
animTimer.scheduleAtFixedRate(new TimerTask() {
int i=0;
#Override
public void run() {
if (i<100) {
primaryStage.setX(primaryStage.getX() - 4);
primaryStage.setY(primaryStage.getY() - 1);
primaryStage.setWidth(primaryStage.getWidth()+8.11);
primaryStage.setHeight(primaryStage.getHeight()+3.19);
} else {
this.cancel();
}
i++;
}
}, 0, 10);
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(10 * 101), ev -> {
primaryStage.setResizable(true);
primaryStage.setScene(new Scene(HomePage));
fullUserName.setText("User"); // Got NullPointerException at this line
}));
timeline.play();
}
public void start(Stage primaryStage) {
try {
Pane root = new Pane();
Scene scene = new Scene(root,400,400);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
loadHomePage(primaryStage);
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
HomePage.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.MenuButton?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<BorderPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="9.0" minWidth="16.0" prefHeight="720.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.HomePage">
<top>
<GridPane maxHeight="-Infinity" minHeight="-Infinity" prefHeight="32.5" style="-fx-background-color: #aeccc9;" BorderPane.alignment="CENTER">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="11.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="27.5" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="11.5" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="10.0" />
<ColumnConstraints hgrow="ALWAYS" maxWidth="-Infinity" minWidth="-Infinity" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="15.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<MenuButton fx:id="fullUserName" mnemonicParsing="false" GridPane.columnIndex="4">
<items>
<MenuItem mnemonicParsing="false" text="Logout" />
<MenuItem mnemonicParsing="false" text="Exit" />
</items>
<graphic>
<ImageView fitHeight="22.0" fitWidth="22.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#Cool-50.png" />
</image>
</ImageView>
</graphic>
<padding>
<Insets bottom="-1.5" left="-1.5" right="-1.5" top="-1.5" />
</padding>
</MenuButton>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Title" GridPane.columnIndex="3">
<font>
<Font name="Arial Rounded MT Bold" size="22.0" />
</font>
</Text>
</children>
</GridPane>
</top>
</BorderPane>
So as you can see, I got a NullPointerException when executing fullUserName.setText("User"); which means that the "fullUserName" menu button is not initialized.
Is it possible for the program to wait until fullUserName (or any other FXML variables for that matter) has been initialized so that I can execute the statement?