JavaFX 8 - Add a graphic to a TitledPane on the right side

java, javafx-8, layout

Solution

Based on the code shown by the OP on his edited question, this code addresses the fact that the titled pane is created on a listener before the stage is shown, on a custom class.

@Override
public void start(Stage primaryStage) {

    Scene scene = new Scene(new StackPane(), 300, 250);

    primaryStage.setScene(scene);

    primaryStage.setOnShown(e -> {
        CustomTitledPane customTitledPane = new CustomTitledPane("Title", new StackPane(new Label("Graphic to the Right")));
        scene.setRoot(customTitledPane);
        customTitledPane.applyCss();
        customTitledPane.layout();

        // title region
        Node titleRegion=customTitledPane.lookup(".title");
        // padding
        Insets padding=((StackPane)titleRegion).getPadding();
        // image width
        double graphicWidth=customTitledPane.getGraphic().getLayoutBounds().getWidth();
        // arrow
        double arrowWidth=titleRegion.lookup(".arrow-button").getLayoutBounds().getWidth();
        // text
        double labelWidth=titleRegion.lookup(".text").getLayoutBounds().getWidth();

        double nodesWidth = graphicWidth+padding.getLeft()+padding.getRight()+arrowWidth+labelWidth;

        customTitledPane.graphicTextGapProperty().bind(customTitledPane.widthProperty().subtract(nodesWidth));
    });

    primaryStage.show();

}

class CustomTitledPane extends TitledPane {

    public CustomTitledPane(String titleText, Node node) {
        super(titleText, node);
        setAnimated(true);
        setCollapsible(true);
        ImageView img = new ImageView(new Image(getClass().getResource("unlock24.png").toExternalForm()));
        img.setFitHeight(10d);
        img.setPreserveRatio(true);
        img.setSmooth(true);
        setGraphic(img);
        setContentDisplay(ContentDisplay.RIGHT);
    }
}

Problem

I want to add a little icon to the title of a `TitledPane`. Therefore I set an empty title and add a `HBox` containing a `Label` and a `ImageView` as graphic. In this way the icon is shown close to the end of the text. I want it to be shown always next to the right border of the `TitledPane`. How can I do this? I also tried to use a `BorderPane` and add the `Label` to the center and the `ImageView` to the right, but the `BorderPane` doesn't get the maximum size of the TitledPane. So I tried to set MaxWidth to Max-Value, but this didn't help Does anybody know what to do? **EDIT: ** The "custom" control I created will be initialized within a method called in stage.setOnShown. ``` public class CustomTitledPane extends TitledPane { private Image alert; private Image registered; private Image deleted; private ImageView img; public CustomTitledPane(String titleText, Node node) { super(titleText, node); setAnimated(true); setCollapsible(true); img = new ImageView(); img.setFitHeight(10d); img.setPreserveRatio(true); img.setSmooth(true); setGraphic(img); setContentDisplay(ContentDisplay.RIGHT); // apply css and force layout of nodes applyCss(); layout(); // title region Node titleRegion = lookup(".title"); // padding Insets padding = ((StackPane) titleRegion).getPadding(); // image width double graphicWidth = img.getLayoutBounds().getWidth(); // arrow double arrowWidth = titleRegion.lookup(".arrow-button") .getLayoutBounds().getWidth(); // text double labelWidth = titleRegion.lookup(".text").getLayoutBounds() .getWidth(); double nodesWidth = graphicWidth + padding.getLeft() + padding.getRight() + arrowWidth + labelWidth; System.out.println("w: " + graphicWidth + " " + arrowWidth + " " + labelWidth); graphicTextGapProperty().bind(widthProperty().subtract(nodesWidth)); try { alert = new Image(new FileInputStream("img/Alert.png")); registered = new Image(new FileInputStream("img/Registered.png")); deleted = new Image(new FileInputStream("img/Deleted.png")); } catch (FileNotFoundException e) { e.printStackTrace(); } } } ``` And here's the CSS for TitledPane: ``` .titled-pane { -fx-text-fill: #006FD8; } .titled-pane > .title { -fx-background-color: transparent; -fx-border-color: linear-gradient(to right, white 0%, grey 30%, grey 70%, white 100%) transparent transparent transparent; } .titled-pane:expanded > .title { -fx-border-color: grey transparent transparent transparent; -fx-background-color: linear-gradient(to bottom, #DCE7F5, white); } .titled-pane:expanded > *.content { -fx-border-width: 0; } ```

Original source