首页 > 解决方案 > 使用三个单选按钮从水平布局切换到垂直布局

问题描述

使用 JavaFX 8,我想要一个带有三个单选按钮的响应式布局,一旦没有足够的水平空间将所有单选按钮放在一起,就会从水平布局变为垂直布局。

这意味着默认布局应该是这样的:

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

一旦没有足够的水平空间将所有三个按钮放在一行上,我希望布局更改为:

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

请注意,我想避免中间状态,例如:

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

我试图通过动态更改其方向的流窗格来实现所需的行为,但是当流窗格下方有另一个控件(例如文本区域)时,我遇到了小的布局故障。这是我使用的代码:

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

}

当我运行此应用程序并仔细更改场景的宽度时,我可以在流窗格的方向从垂直更改为水平后立即看到以下布局故障:

在此处输入图像描述

如您所见,单选按钮和文本区域之间有一个不需要的空白区域。当我进一步增加场景宽度或窗口失去焦点时,它就会消失。在流窗格周围有更多控件和容器的更大应用程序中,我可以看到更多的布局故障,所以我想知道是否有更好的方法来实现我需要的响应能力。

我可以做些什么来改善流窗格的行为?或者是否有更合适的布局窗格可以用于此?

我会很感激任何支持。谢谢。

标签: javajavafx

解决方案


VBox您可以在和之间切换HBox。看看这是否符合您的要求。

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

}

推荐阅读