【问题标题】:JavaFX 8 - Add a graphic to a TitledPane on the right sideJavaFX 8 - 将图形添加到右侧的 TitledPane
【发布时间】:2014-11-24 08:25:32
【问题描述】:

我想在TitledPane 的标题上添加一个小图标。因此,我设置了一个空标题并添加了一个 HBox,其中包含一个 Label 和一个 ImageView 作为图形。这样,图标显示在文本末尾附近。我希望它始终显示在TitledPane 的右边框旁边。 我怎样才能做到这一点? 我还尝试使用BorderPane 并将Label 添加到中心并将ImageView 添加到右侧,但是BorderPane 没有获得TitledPane 的最大大小。 所以我尝试将 MaxWidth 设置为 Max-Value,但这并没有帮助

有人知道该怎么做吗?

**编辑:** 我创建的“自定义”控件将在 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();
    }
} }

这是 TitledPane 的 CSS:

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

【问题讨论】:

    标签: java layout javafx-8


    【解决方案1】:

    根据 OP 在他编辑的问题上显示的代码,此代码解决了这样一个事实:标题窗格是在显示阶段之前在侦听器上创建的,在自定义类上。

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

    【讨论】:

    • 但是当我在场景中有另一个节点时,我无法将场景的根设置为 titledPane 还是我错了?
    • 为了简单起见,我使用的是根目录。您只需要将您的 titledPane 作为子项添加到正确的容器中。
    • 现在工作。非常感谢您的帮助!
    • 抱歉,还有一个问题。当我折叠 TitledPane 时,它​​每次都会变宽。当我关闭 TitledPane 时同样的问题。这怎么可能??
    • 那么问题不在于标题区域的渲染!问题是:您的标题窗格位于允许调整大小的容器中;内容使它成长。在这种情况下,使用ScrollPane 来包装内容。您还可以设置标题窗格的大小(最小/首选项/最大)。
    【解决方案2】:

    无需将图形和文本包装在一个框中,因为您可以使用setContentDisplay() 选择如何显示您的内容:

    title.setContentDisplay(ContentDisplay.RIGHT);
    

    一旦你有了右边的图像,你需要设置图像和文本之间的间隙。为此,一旦显示舞台,我们可以使用一些查找来获取标题中节点的真实尺寸。

    最后,我们将间隙空间绑定到标题的宽度属性减去这些尺寸。

    编辑

    示例现在支持在显示阶段之前创建。

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

    这就是它的样子:

    【讨论】:

    • 感谢您的快速回答,但我在.getPadding() 和每个.lookup() 方法上都收到了NullPointerException
    • lookup 尝试查找 CSS 选择器。如果未找到选择器,则返回 Node 或 null。您是否将自定义 CSS 应用于您的 titledPane?然后你应该寻找你的选择器。无论如何,尝试运行我的示例并检查它是否适合您。
    • 是的,我正在应用自定义 CSS,但这不是问题,因为您的示例在测试应用程序中可以正常工作。那么还有什么可能导致 NullPointerException?
    • 首先,必须在舞台显示后调用lookup。即使您将自定义选择器应用于您的TitledPane,也要查找此.title,因为这是来自TitleRegion 子项的选择器。你知道ScenicView吗?它将帮助您找到您的选择器。
    • 这就是问题所在...您必须在显示阶段之前定义侦听器,但那时查找将失败。你可以打电话给title.applyCss(),你不会得到NPE,但所有的宽度都是0。
    猜你喜欢
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多