Переключение с горизонтального на вертикальное расположение с тремя переключателями - PullRequest
0 голосов
/ 25 января 2019

Используя 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);
        }
    }

}

Когда я запускаю это приложение и тщательно изменяю ширину сцены, я вижу следующий глюк компоновки сразу после изменения ориентации панели потока с вертикальной на горизонтальную:

enter image description here

Как видите, между переключателями и текстовой областью существует нежелательное пустое пространство.Он исчезает, когда я увеличиваю ширину сцены или если окно теряет фокус.В более крупном приложении с большим количеством элементов управления и контейнеров на панели потоков я вижу еще больше сбоев компоновки, поэтому мне интересно, есть ли лучший подход к достижению нужной мне скорости реагирования.

Что можно сделать, чтобыулучшить поведение панели потока?Или есть более подходящая панель макета, которую я мог бы использовать для этого?

Буду признателен за любую поддержку.Спасибо.

1 Ответ

0 голосов
/ 26 января 2019

Вы можете переключаться между 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;
            }
        }
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...