JavaFX 11: добавление графического элемента в TitledPane с правой стороны - PullRequest
0 голосов
/ 22 сентября 2018

Это связано с предыдущим вопросом, заданным более трех лет назад. JavaFX 8 - Добавить изображение в TitledPane с правой стороны

Мне не нравится это решение, и я не нашел других решений.

Многопроизошло с JavaFX, так как этот оригинальный вопрос был задан для JavaFX 8. Недавно был выпущен JavaFX 11.

У меня есть проект, использующий JavaFX 11. Графический объект TitledPane установлен с HBox, содержащим одну кнопку, которую я хочу разместить накрайняя правая сторона заголовка.

TitledPane titledPane = new TitledPane();
titledPane.setText("Title");

HBox titleBox = new HBox();
Button b1 = new Button("ClickMe!");
titleBox.getChildren().add(b1);

titledPane.setGraphic(titleBox);
titledPane.setContentDisplay(ContentDisplay.RIGHT);

При установке выравнивания области заголовка на CENTER_RIGHT заголовок будет располагаться справа, но весь заголовок, текст и графика.

titledPane.setAlignment(Pos.CENTER_RIGHT);

Iпробовал экспериментировать с различными контейнерами в графике TitledPane, HBox, GridPane.Настройка увеличения, выравнивания, заполнения, ширины и т. Д. Ничего не работает.

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

    primaryStage.setOnShown(e -> {
        for (TitledPane titledPane : panes) {
            Node titleRegion = titledPane.lookup(".title");
            Insets padding = ((StackPane) titleRegion).getPadding();
            double graphicWidth = titledPane.getGraphic().getLayoutBounds().getWidth();
            double arrowWidth = titleRegion.lookup(".arrow-button").getLayoutBounds().getWidth();
            double labelWidth = titleRegion.lookup(".text").getLayoutBounds().getWidth();
            double nodesWidth = graphicWidth + padding.getLeft() + padding.getRight() + arrowWidth + labelWidth;
            titledPane.graphicTextGapProperty().bind(titledPane.widthProperty().subtract(nodesWidth));
        }
    });

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

Вам не нужно использовать контейнеры для графического узла - просто переведите его вправо:

TitledPane titledPane = new TitledPane("Title", null);
titledPane.setPrefSize(400, 200);

Button graphic = new Button("Click me!");
titledPane.setGraphic(graphic);
titledPane.setContentDisplay(ContentDisplay.RIGHT);

final double graphicMarginRight = 10; //change it, if needed

graphic.translateXProperty().bind(Bindings.createDoubleBinding(
    () -> titledPane.getWidth() - graphic.getLayoutX() - graphic.getWidth() - graphicMarginRight,
    titledPane.widthProperty())
);

Screenshot

0 голосов
/ 22 сентября 2018

Я не уверен, что полностью понимаю вашу цель, но я верю, что вы хотите, чтобы TitledPane имел и Label, и Button с Label выровненными по левому краю и Button выровненными по правому краю, правильными?

Для того, чтобы сделать это, требуется немного обходного пути и использование контейнеров JavaFX.Прежде всего, нет необходимости устанавливать заголовок для самого TitledPane;мы добавим Label к нашему графику в качестве заголовка.

В приведенном ниже примере мы будем использовать HBox для хранения всех узлов, которые мы хотим в TitledPaneHBox мы добавляем Region, который всегда будет расти в пределах HBox.Это заставляет Button полностью направо.

Тогда, поскольку TitledPane имеет полуфиксированную максимальную ширину для его графики, нам нужно привязать наш HBox к ширинеTitledPane, с отступом, чтобы избежать наложения стрелки "развернуть".

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        // Simple interface
        VBox root = new VBox(5);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // Create the TitlePane
        TitledPane titledPane = new TitledPane();
        titledPane.setAlignment(Pos.CENTER);

        // Create HBox to hold our Title and button
        HBox contentPane = new HBox();
        contentPane.setAlignment(Pos.CENTER);

        // Set padding on the left side to avoid overlapping the TitlePane's expand arrow
        // We will also pad the right side
        contentPane.setPadding(new Insets(0, 10, 0, 35));

        // Now, since the TitlePane's graphic node generally has a fixed size, we need to bind our
        // content pane's width to match the width of the TitledPane. This will account for resizing as well
        contentPane.minWidthProperty().bind(titledPane.widthProperty());

        // Create a Region to act as a separator for the title and button
        HBox region = new HBox();
        region.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(region, Priority.ALWAYS);

        // Add our nodes to the contentPane
        contentPane.getChildren().addAll(
                new Label("Titles Are Cool"),
                region,
                new Button("Click me!")
        );

        // Add the contentPane as the graphic for the TitledPane
        titledPane.setGraphic(contentPane);

        // Add the pane to our root layout
        root.getChildren().add(titledPane);

        // Show the Stage
        primaryStage.setWidth(400);
        primaryStage.setHeight(300);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
}

Результат:

Screenshot

Это довольно чистое решение, и я бы не стал считать его "взломом".Просто используя контейнеры и структуры JavaFX так, как они были задуманы.

...