Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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;
}
like image 745
S.Pro Avatar asked Feb 11 '23 12:02

S.Pro


1 Answers

There's no need to wrap graphic and text in a box, since you can select how to display your content with setContentDisplay():

title.setContentDisplay(ContentDisplay.RIGHT);

Once you have the image at the right you need to set the gap between the image and the text. For that, we can use some lookups to get the real dimensions of the nodes in the title, once the stage is shown.

Finally, we bind the gap space to the width property of the title subtracting those dimensions.

EDIT

The sample now supports creation before the stage is shown.

@Override
public void start(Stage primaryStage) {
    Scene scene = new Scene(new StackPane(), 300, 250);

    primaryStage.setScene(scene);

    primaryStage.setOnShown(e -> {
        TitledPane title = new TitledPane("Title",
                new StackPane(new Label("Graphic to the Right")));

        ImageView imageView = new ImageView(new Image(getClass().getResource("unlock24.png").toExternalForm()));

        title.setGraphic(imageView);
        title.setContentDisplay(ContentDisplay.RIGHT);

        scene.setRoot(title);

        // apply css and force layout of nodes
        title.applyCss();
        title.layout();

        // title region
        Node titleRegion=title.lookup(".title");
        // padding
        Insets padding=((StackPane)titleRegion).getPadding();
        // image width
        double graphicWidth=imageView.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;  

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

    primaryStage.show();

}

And this is how it looks like:

Titled Pane

like image 52
José Pereda Avatar answered Feb 14 '23 03:02

José Pereda