I have a FlowPane
wrapped in a ScrollPane
. FlowPane
orientation is Vertical
, so it will wrap the controls. But I want to set the FlowPane
to resize vertically if the columns size is greater than the width of ScrollPane
. I've tried a lot of settings, both on ScrollPane
and FlowPane
but none of them helped me with my wish.
As an image of how I want to do is something like this:
(red contur is ScrollPane
, green is FlowPane
)
Containers, after the flow pane is populated, with ScrollPane
's width more than two columns of controls:
How it works right now, after resizing:
How I want to do after resizing the ScrollPane
:
Can this be achieved? What settings I must do to both ScrollPane
and FlowPane
?
Edit:
Minimal reproduction code:
hello-view.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.text.Font?>
<AnchorPane prefHeight="424.0" prefWidth="457.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.demo.HelloController">
<children>
<AnchorPane layoutX="14.0" layoutY="14.0" prefHeight="399.0" prefWidth="430.0" style="-fx-border-color: #555555;" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="14.0">
<children>
<ScrollPane fitToHeight="true" fitToWidth="true" focusTraversable="false" hbarPolicy="NEVER" layoutX="14.0" layoutY="13.0" maxWidth="1.7976931348623157E308" prefHeight="377.0" prefWidth="404.0" style="-fx-border-color: red; -fx-border-width: 2;" AnchorPane.bottomAnchor="7.0" AnchorPane.leftAnchor="13.0" AnchorPane.rightAnchor="12.0" AnchorPane.topAnchor="12.0">
<content>
<FlowPane maxWidth="1.7976931348623157E308" orientation="VERTICAL" prefHeight="363.0" prefWidth="397.0" rowValignment="TOP" style="-fx-border-color: green; -fx-border-width: 2;">
<children>
<Button mnemonicParsing="false" prefHeight="121.0" prefWidth="140.0" text="1">
<FlowPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</FlowPane.margin>
<font>
<Font name="System Bold" size="24.0" />
</font>
</Button>
<Button layoutX="12.0" layoutY="12.0" mnemonicParsing="false" prefHeight="121.0" prefWidth="140.0" text="2">
<FlowPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</FlowPane.margin>
<font>
<Font name="System Bold" size="24.0" />
</font>
</Button>
<Button layoutX="10.0" layoutY="135.0" mnemonicParsing="false" prefHeight="121.0" prefWidth="140.0" text="3">
<FlowPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</FlowPane.margin>
<font>
<Font name="System Bold" size="24.0" />
</font>
</Button>
<Button layoutX="154.0" layoutY="10.0" mnemonicParsing="false" prefHeight="121.0" prefWidth="140.0" text="4">
<FlowPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</FlowPane.margin>
<font>
<Font name="System Bold" size="24.0" />
</font>
</Button>
</children>
</FlowPane>
</content>
</ScrollPane>
</children>
</AnchorPane>
</children>
</AnchorPane>
HelloController.java:
package com.example.demo;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class HelloController {
@FXML
private Label welcomeText;
@FXML
protected void onHelloButtonClick() {
welcomeText.setText("Welcome to JavaFX Application!");
}
}
HelloApplication.java
package com.example.demo;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 320, 240);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
HelloApplication.java
and HelloController.java
are default demo files from starting project in JavaFX.
Conclusion:
Is there a combination of properties for ScrollPane
and FlowPane
to be able to resize the FlowPane
vertically and stop resizing in the right when the control inside tries to move to create a new column (this happens when ScrollPane
resize vertically)? I don't want to create those invisible columns in the right, instead grows the FlowPane vertically!
Mention: this could happens in two way
- when resize form from the bottom, and the controls from the bottom of the
FlowPane
will move to the top, and theFlowPane
will resize automatically to the right and put the controls in the hidden area ofFlowPane
, (and) - When you resize form horizontally and there is no more space to move the controls from the right column to the next row, so the
FlowPane
will not stay anchored to right and to try to create an "invisible" row (or as many as it takes to move needed controls down).
I hope I make it clear as possible.
This answer I found it myself and it works only for
FlowPane
containing controls with the same size.Purpose: Allow user to populate a
FlowPane
inVertical
orientation, with parentScrollPane
's scrollbars set only to vertical scrollbar visible (when needed) and theFlowPane
width to fitScrollPane
's width always.Starting from a demo project in JavaFX, this is the fxml file which contains definition for the main-view (hello-view.fxml in this case).
hello-view.fxml
file:HelloController.java
file:HelloApplication.java
file:The approach was to wrap the
FlowPane
in aAnchorPane
.FlowPane
is anchored inAnchorPane
to all bounds. TheAnchorPane
is wrapped inScrollPane
.In controller I've created a public method in which I added listners to
widthProperty()
andheightProperty()
ofScrollPane
to be able to calculate the rows needed for resizing theAnchorPane
, based on how many items are inFlowPane
and how many columns could be made with theScrollPane
's width. This method was added because size of controls must be read after the scene is displayed, which I've done it inHelloApplication.java
main class. In this way listners are added after all items are displayed, and it will be calculated correctly.Demo: