How to automatically resize JavaFX containers when window is maximized? - javafx

Basically, I have the following document:
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXTabPane?>
<?import com.jfoenix.controls.JFXTreeView?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="566.0" prefWidth="753.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gui.controller">
<center>
<JFXTabPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" BorderPane.alignment="CENTER">
<tabs>
<Tab text="TAB">
<content>
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<VBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="495.0" prefWidth="753.0">
<children>
<StackPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="150.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
<children>
<HBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" nodeOrientation="LEFT_TO_RIGHT" prefHeight="100.0" prefWidth="200.0">
<children>
<JFXTreeView fx:id="treeView" />
<TableView maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="277.0" prefWidth="753.0">
<columns>
<TableColumn maxWidth="-1.0" text="COL" />
<TableColumn text="COL" />
<TableColumn text="COL" />
<TableColumn text="COL" />
<TableColumn minWidth="0.0" text="COL" />
<TableColumn text="COL" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</children>
</HBox>
</children>
</StackPane>
</children>
</VBox>
</children>
</AnchorPane>
</content>
</Tab>
</tabs>
</JFXTabPane>
</center>
</BorderPane>
The main class to load the FXML document:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
BorderPane parent = (BorderPane) FXMLLoader.load(getClass().getResource("document.fxml"));
Scene scene = new Scene(parent);
primaryStage.setScene(scene);
primaryStage.show();
}
}
When i maximize the window, the table and the rest of the containers don't resize accordingly. I tried to set Max Width and Max Height for all the containers to MAX_VALUE in SceneBuilder but nothing really happens.
Is there a way to automatically expand the containers so that they can use all the space when the window is maximized ?

After spending some time investigating the problem. The steps that have corrected the issue are :
1- Setting all the anchor pane constraints to 0 (In the VBox tag) will allow for the child container to occupy all the space provided by the parent.
<VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
2- Setting the Hgrow attribute of the TabeView to Always will allow for the table to grow horizontally whenever it finds space.
3- For the rest of the containers, keeping the default settings and setting Max Height and Max Width to USE_COMPUTED_SIZE will do the trick.

Here is a start: a border pane that will grow with scene:
public void start(Stage stage) {
BorderPane root = new BorderPane();
root.setStyle("-fx-background-color: yellow");
root.setCenter(new Text("center"));
root.setTop(new Text("top"));
root.setBottom(new Text("bottom"));
Scene scene = new Scene(root);
root.prefHeightProperty().bind(scene.heightProperty());
root.prefWidthProperty().bind(scene.widthProperty());
stage.setScene(scene);
stage.show();
}

Related

javaFx layoutBounds initialize issue

in Controller implement Initializable the initialize method I want get box LayoutBounds,but why layoutBounds all property is zero?
package com.erayt.studio.process.component.aggregate.controller;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.VBox;
import java.net.URL;
import java.util.ResourceBundle;
public class TestController implements Initializable {
#FXML
private VBox box;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
System.out.println(box.getLayoutBounds());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<VBox fx:id="box" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.erayt.studio.process.component.aggregate.controller.TestController">
<children>
<TabPane prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab text="Untitled Tab 1">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Untitled Tab 2">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
</tabs>
</TabPane>
</children>
</VBox>

Why when I shrink my splitPane a grey area appears?

I have a problem with my fxml interface.
When I try to reduce a specific part of my application, a grey area covers it.
An example in image will be more speaking:
I've tried quite a few things (by modifying parameters of the different components) but the white zone is still there.
Do you have any idea what my problem is?
The code (example):
MainApp.java
public class MainApp extends Application {
#Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/test.fxml"));
AnchorPane root = (AnchorPane) loader.load();
Controller controller = loader.getController();
controller.setMainApp(this);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
Controller.java
public class Controller implements Initializable{
MainApp mainApp;
#FXML
Label label;
#Override
public void initialize(URL location, ResourceBundle resources) {
label.setText("Hello");
}
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
}
}
test.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane id="AnchorPane"
maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
minHeight="250.0" minWidth="400.0" prefHeight="519.0" prefWidth="921.0"
xmlns="http://javafx.com/javafx/8.0.111"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="application.view.Controller">
<children>
<SplitPane dividerPositions="0.49439102564102566"
maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
prefHeight="799.0" prefWidth="1250.0" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="400.0" minWidth="400.0"
prefHeight="511.0" prefWidth="467.0" rotate="0.0" />
<AnchorPane minHeight="0.0" minWidth="0.0"
prefHeight="797.0" prefWidth="349.0">
<children>
<SplitPane layoutX="17.0" layoutY="7.0"
orientation="VERTICAL" prefHeight="797.0" prefWidth="346.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane maxHeight="1.7976931348623157E308"
maxWidth="1.7976931348623157E308" minHeight="108.0"
minWidth="447.0" prefHeight="108.0" prefWidth="447.0">
<children>
<SplitPane dividerPositions="0.5248796147672552"
maxHeight="1.7976931348623157E308"
maxWidth="1.7976931348623157E308" minHeight="-Infinity"
minWidth="-Infinity" prefHeight="112.0" prefWidth="442.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane maxHeight="1.7976931348623157E308"
maxWidth="1.7976931348623157E308" minHeight="0.0"
minWidth="0.0" prefHeight="110.0" prefWidth="313.0" />
<AnchorPane maxHeight="1.7976931348623157E308"
maxWidth="1.7976931348623157E308" minHeight="0.0"
minWidth="0.0" prefHeight="110.0" prefWidth="87.0">
<children>
<Label fx:id="label" layoutX="52.0" layoutY="223.0"
prefHeight="16.0" prefWidth="96.0" text="Test !">
<font>
<Font size="29.0" />
</font>
</Label>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
Note: I made this interface with the help of Gluon's SceneBuilder.
Thank you in advance.
In SceneBuilder if I click on the root SplitPane and slide it's divider to the right, I get this picture below. This means that at some point your min values on the highlighted AnchorPane is greater than it's parent's current width.
I basically set most of the later AnchorPanes' preferred width to USE_COMPUTER_SIZE and the highlighted AnchorPane's min width to USE_PRE_SIZE and it's preferred width to USE_COMPUTER_SIZE. Here is the code I used to fix the problem:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane id="AnchorPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="250.0" minWidth="400.0" prefHeight="519.0" prefWidth="921.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.view.Controller">
<children>
<SplitPane dividerPositions="0.49836779107725787" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="799.0" prefWidth="1250.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="400.0" minWidth="400.0" prefHeight="511.0" prefWidth="467.0" rotate="0.0" />
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="797.0" prefWidth="349.0">
<children>
<SplitPane layoutX="17.0" layoutY="7.0" orientation="VERTICAL" prefHeight="797.0" prefWidth="346.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane>
<children>
<SplitPane dividerPositions="0.5248796147672552" minHeight="-Infinity" minWidth="-Infinity" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="0.0" minWidth="0.0" />
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="0.0" minWidth="0.0" prefHeight="110.0" prefWidth="87.0">
<children>
<Label fx:id="label" layoutX="52.0" layoutY="223.0" prefHeight="16.0" prefWidth="96.0" text="Test !">
<font>
<Font size="29.0" />
</font>
</Label>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>

JavaFX how to handle titledpane expandproperty?

I'm testing an application which can write texts to a TextArea as soon as I open a TitlePane. I coded my app so that when I click the title of titlepane2, some text should be written in the textArea2 and it's working fine.
But the problem is: how can some text be written when I click the finish button located in titlepane1?
As you can see, if the finish button clicked, titlepane2 is going to be expanded and some text should be written in textArea2.
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextArea;
import javafx.scene.control.TitledPane;
public class TitlePaneTestController implements Initializable {
#FXML private TitledPane titlePane1;
#FXML private TitledPane titlePane2;
#FXML private TextArea textArea1;
#FXML private TextArea textArea2;
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML
private void handleTitlePane1Clicked() {
textArea1.appendText("This is TitlePane 1");
}
#FXML
private void handleTitle1Finished() {
titlePane1.setExpanded(false);
titlePane2.setExpanded(true);
}
#FXML
private void handleTitlePane2Clicked() {
textArea2.appendText("This is TitlePane 2");
}
}
this is the FXML file
<?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="smallframework.TitlePaneTestController">
<children>
<Accordion layoutX="107.0" layoutY="101.0" prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<panes>
<TitledPane fx:id="titlePane1" animated="false" text="Step 1">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<VBox prefHeight="353.0" prefWidth="598.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<TextArea fx:id="textArea1" prefHeight="200.0" prefWidth="200.0" />
<Button mnemonicParsing="false" onAction="#handleTitle1Finished" text="Finish" />
</children>
</VBox>
</children>
</AnchorPane>
</content>
</TitledPane>
<TitledPane fx:id="titlePane2" animated="false" text="Step 2">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<VBox prefHeight="353.0" prefWidth="598.0">
<children>
<TextArea fx:id="textArea2" prefHeight="200.0" prefWidth="200.0" />
<Button mnemonicParsing="false" text="Finish" />
</children>
</VBox>
</children>
</AnchorPane>
</content>
</TitledPane>
</panes>
</Accordion>
</children>
</AnchorPane>
Register a listener with the expandedProperty of each titled pane:
#Override
public void initialize(URL url, ResourceBundle rb) {
titlePane1.expandedProperty().addListener((obs, wasExpanded, isNowExpanded) -> {
if (isNowExpanded) {
textArea1.appendText("Titled Pane 1 selected");
}
}
titlePane2.expandedProperty().addListener((obs, wasExpanded, isNowExpanded) -> {
if (isNowExpanded) {
textArea2.appendText("Titled Pane 2 selected");
}
}
}

Click through empty areas in a JavaFX VBox

I have a VBox that is in a BorderPane (on the left side) so it is automatically sized to the full BorderPane height. I place a number of panels in this VBox, but they do not take up the full height, meaning that there is some empty space at the bottom. The BorderPane is in turn in a StackPane, so there are layers "underneath" it.
What I would like is for mouse-clicks in this empty space to be passed through to the pane underneath the BorderPane. Web searches have led me to believe that the correct way to do this is to make the VBox transparent, and set it to pickOnBounds="false".
I have tried to make the VBox transparent with both style="-fx-background-color: rgba(0,0,0,0);" and opacity="0", but neither produces the required effect — it seems that even when transparent with pickOnBounds="false", the VBox still consumes mouse events in its empty area and does not allow them to fall through to the next layer down in the StackPane.
The following FXML illustrates the problem. Two toggle buttons are on the bottom layer of a StackPane. On the left-hand side, the button is covered by a VBox, and it cannot be clicked. On the right-hand side, the button is covered by an AnchorPane, and it can be clicked.
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<StackPane fx:id="stackPane" 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">
<children>
<AnchorPane fx:id="anchorPane">
<children>
<ToggleButton mnemonicParsing="false" text="ToggleButton under VBox" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" />
<ToggleButton mnemonicParsing="false" text="ToggleButton under AnchorPane" AnchorPane.bottomAnchor="0.0" AnchorPane.rightAnchor="0.0" />
</children>
</AnchorPane>
<BorderPane fx:id="borderPane" pickOnBounds="false" prefHeight="200.0" prefWidth="200.0">
<left>
<VBox fx:id="vBox" pickOnBounds="false" prefHeight="200.0" prefWidth="400.0" style="-fx-background-color: rgba(0,0,0,0);" BorderPane.alignment="CENTER">
<children>
<TitledPane animated="false" text="untitled">
<content>
<AnchorPane fx:id="pane1" minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="400.0" />
</content>
</TitledPane>
<TitledPane animated="false" text="untitled">
<content>
<AnchorPane fx:id="pane2" minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="400.0" />
</content>
</TitledPane>
</children>
</VBox>
</left>
<center>
<AnchorPane pickOnBounds="false" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
</children>
</StackPane>
Is there any workaround for this problem?
Write:
-fx-background-color: null;
Instead of:
-fx-background-color: rgba(0,0,0,0);
I do not know why setting the background to null and not transparent works in this case (as I expected that the transparent background would also work fine).

How to set/remove insets in JavaFX TitledPane

I've created a TitledPane in JavaFX with a single child component (a button) as follows:
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TitledPane animated="false" layoutX="137.0" layoutY="60.0" prefHeight="400.0" prefWidth="600.0" text="untitled" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" >
<children >
<Button layoutX="193.1875" layoutY="133.5" mnemonicParsing="false" prefHeight="374.0" prefWidth="598.0" text="Button" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</content>
</TitledPane>
</children>
</AnchorPane>
This appears as below. There is quite a bit a spacing around the button, I'd like to reduce this to either 0 or maybe, a single pixel. I don't see any property of either the AnchorPane or the TitledPane that will do this. Is there such a property?
Use Scenic View to figure out issues like this.
The AnchorPane inside the TitledPane has padding of 0.8em (10px) on all sides. This is defined in the default stylesheet, modena.css. You can reset it in the FXML:
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TitledPane animated="false" text="untitled" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content>
<AnchorPane >
<padding>
<Insets top="0" right="0" left="0" bottom="0"/>
</padding>
<children >
<Button mnemonicParsing="false" text="Button" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</content>
</TitledPane>
</children>
</AnchorPane>
or with an external style sheet with
.titled-pane > * > * > AnchorPane {
-fx-padding: 0em ;
}
I already answered on a similar question, but I also want to post it here, since it also perfectly matches this question.
To extend #James_D's answer:
If you do not use AnchorPane as the TitledPane's content, but some other node, you have to adjust the CSS accordingly.
A universal CSS solution for removing padding on a TitledPane's content, no matter which type of Node is used as content, is the following:
.titled-pane > .content > * {
-fx-padding: 0px;
}
This sets the padding for any child of the TitledPane's content to 0px.

Resources