Switching from a horizontal to a vertical layout with three radio buttons

Uwe :

Using JavaFX 8, I would like to have a responsive layout with three radio buttons that changes from a horizontal layout to a vertical layout as soon as there is not enough horizontal space to put all radio buttons next to each other.

This means the default layout should be like this:

(x) Radio button 1  ( ) Radio button 2  ( ) Radio button 3

And as soon as there is not enough horizontal space to put all three buttons on a single line, I want the layout to change to this:

(x) Radio button 1
( ) Radio button 2
( ) Radio button 3

Note that I want to avoid intermediate states like:

(x) Radio button 1  ( ) Radio button 2
( ) Radio button 3

I have tried to achieve the desired behaviour with a flow pane that changes its orientation dynamically but I encountered small layout glitches when there was another control (e.g. a text area) positioned underneath the flow pane. Here's the code I have used:

import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextArea;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ResponsiveLayout extends Application {

    RadioButton radioButton1 = new RadioButton("Radio button 1");
    RadioButton radioButton2 = new RadioButton("Radio button 2");
    RadioButton radioButton3 = new RadioButton("Radio button 3");
    FlowPane flowPane = new FlowPane(radioButton1, radioButton2, radioButton3);

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        flowPane.setHgap(10);
        flowPane.setPrefWrapLength(60);
        flowPane.widthProperty().addListener((obs, oldWidth, newWidth) -> updateOrientation(newWidth));

        VBox container = new VBox(flowPane, new TextArea());

        Scene scene = new Scene(container, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void updateOrientation(Number paneWidth) {
        double childrenPadding = flowPane.getHgap() * (flowPane.getChildren().size() - 1);
        int extraPadding = 5;
        double childrenWidth = radioButton1.getWidth() +
                               radioButton2.getWidth() +
                               radioButton3.getWidth() +
                               childrenPadding +
                               extraPadding;
        if (paneWidth.doubleValue() < childrenWidth) {
            flowPane.setOrientation(Orientation.VERTICAL);
        } else {
            flowPane.setOrientation(Orientation.HORIZONTAL);
        }
    }

}

When I run this application and carefully change the width of the scene, I can see the following layout glitch right after the orientation of the flow pane changed from vertical to horizontal:

enter image description here

As you can see, there is an unwanted empty space between the radio buttons and the text area. It vanishes when I increase the scene width further or if the window loses focus. In a bigger application with more controls and containers around the flow pane, I can see even more layout glitches so I'm wondering if there is a better approach to achieving the responsiveness I need.

What could I do to improve the flow pane behavior? Or is there a more suitable layout pane that I could use for this?

I'd appreciate any support. Thanks.

Sedrick :

You could toggle between VBox and HBox. See if this meets your requirements.

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Control;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextArea;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ResponsiveLayout extends Application
{

    RadioButton radioButton1 = new RadioButton("Radio button 1");
    RadioButton radioButton2 = new RadioButton("Radio button 2");
    RadioButton radioButton3 = new RadioButton("Radio button 3");
    HBox hBox = new HBox(radioButton1, radioButton2, radioButton3);
    StackPane stackPane = new StackPane(hBox);
    VBox vBox = new VBox();
    boolean isHBox = true;
    double controlWidth = -1;

    public static void main(String[] args)
    {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage)
    {
        hBox.setMaxSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);
        stackPane.setAlignment(Pos.CENTER_LEFT);

        VBox container = new VBox(stackPane, new TextArea());

        Scene scene = new Scene(container, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();

        container.widthProperty().addListener((obs, oldWidth, newWidth) -> updateOrientation(newWidth));
    }

    private void updateOrientation(Number paneWidth)
    {
        if (isHBox) {
            if (hBox.getWidth() == stackPane.getWidth()) {
                controlWidth = hBox.getWidth();
                vBox.getChildren().addAll(hBox.getChildren());
                stackPane.getChildren().clear();
                stackPane.getChildren().add(vBox);
                isHBox = false;
            }
        }
        else {
            if (controlWidth <= stackPane.getWidth()) {
                hBox.getChildren().addAll(vBox.getChildren());
                stackPane.getChildren().clear();
                stackPane.getChildren().add(hBox);
                isHBox = true;
            }
        }
    }

}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=153343&siteId=1