JavaFX 2 中的 GroupBox / TitledBorder?

GroupBox / TitledBorder in JavaFX 2?

提问人:stefan.at.kotlin 提问时间:2/14/2013 更新时间:2/13/2023 访问量:35716

问:

JavaFX 2 上是否有类似 GroupBoxTitledBorder 的东西?

感谢您的任何提示:-)

布局 javafx-2 groupbox titled-border

评论

0赞 SedJ601 7/26/2023
另请参阅 stackoverflow.com/q/76750473/2423906

答:

0赞 Alexander Kirov 2/14/2013 #1

GroupBox - 据我所知,这是通常的组布局。

TitledBorder - 看起来像一个 TitledPane(它通常是 Accordion 的一个组件,但可以是一个单独存在的控件)。

JavaFX-2 类似物看起来与您的不同(但不是显着),并且像往常一样,您可以使用不同的方法来更改控件外观:css、控件的皮肤替换等

53赞 jewelsea 2/14/2013 #2

除非您需要此答案中的自定义样式,否则我更喜欢 Andriy Kryvtsun 的带有 setCollapsible(false) 解决方案的 TitledPane。有关使用,请参阅 TitledPane 教程


没有这种精确的标准控制,但很容易创建自己的控制。下面是一个示例实现:

/** Places content in a bordered pane with a title. */
class BorderedTitledPane extends StackPane {
  BorderedTitledPane(String titleString, Node content) {
    Label title = new Label(" " + titleString + " ");
    title.getStyleClass().add("bordered-titled-title");
    StackPane.setAlignment(title, Pos.TOP_CENTER);
 
    StackPane contentPane = new StackPane();
    content.getStyleClass().add("bordered-titled-content");
    contentPane.getChildren().add(content);
 
    getStyleClass().add("bordered-titled-border");
    getChildren().addAll(title, contentPane);
  }
}

以及随附的 css:

.label {
  -fx-font: 28px Vivaldi;
}

.bordered-titled-title {
  -fx-background-color: white;
  -fx-translate-y: -16;
}
 
.bordered-titled-border {
  -fx-content-display: top;
  -fx-border-insets: 20 15 15 15;
  -fx-background-color: white;
  -fx-border-color: black;
  -fx-border-width: 2;
}
 
.bordered-titled-content {
  -fx-padding: 26 10 10 10;
}

该代码来自我创建的一个示例,该示例是为了响应 Oracle JavaFX 论坛帖子“Equivalent to BorderFactory.createTitledBorder”。

示例程序的输出如下所示。

gettysburg

评论

0赞 stefan.at.kotlin 2/14/2013
太棒了,谢谢!你有没有想过一个可以完全使用FXML使用的版本,因此可以在FXML中设置标题和内容?
0赞 stefan.at.kotlin 2/14/2013
得到了一个FXML版本,请参阅下面的答案。但是,我需要一个普通/较小的字体,在这种情况下,标题没有在边框的中心(垂直!) - 对此有任何提示吗?修好了,请看下面的答案。
0赞 stefan.at.kotlin 2/14/2013
jewelsea,您能否将 Oracle 论坛的链接添加回此线程(适用于 FXML 版本)?
0赞 stefan.at.kotlin 2/14/2013
嗯,较长的标题有问题,请参阅下面的答案。对此有什么提示吗?):将 cotnent 宽度绑定到标签宽度 + 一些偏移量左右?
1赞 Abhishek K 7/23/2016
在实现中遇到问题,只有在我更改 getChildren().addAll(title, contentPane) 后才有效;到 getChildren().addAll(contentPane, title);
14赞 stefan.at.kotlin 2/14/2013 #3

FXML版本的jewelsea的回答:

TitledBorder(我将 BorderedTitledPane 重命名为 TitledBorder)

package com.example.controls;

import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;

public class TitledBorder extends StackPane 
{
    private Label titleLabel = new Label();
    private StackPane contentPane = new StackPane();
    private Node content;



    public void setContent(Node content)
    {
        content.getStyleClass().add("bordered-titled-content");
        contentPane.getChildren().add(content);
    }


    public Node getContent()
    {
        return content;
    }


    public void setTitle(String title)
    {
    titleLabel.setText(" " + title + " ");
    }


    public String getTitle()
    {
        return titleLabel.getText();
    }



    public TitledBorder() 
    {
        titleLabel.setText("default title");
        titleLabel.getStyleClass().add("bordered-titled-title");
        StackPane.setAlignment(titleLabel, Pos.TOP_CENTER);

        getStyleClass().add("bordered-titled-border");
        getChildren().addAll(titleLabel, contentPane);
      }

}

FXML 用法:

<?import com.example.controls.*?>

<TitledBorder title="title" >       
    <Label text="label with text" />        
</TitledBorder>   

别忘了样式表!

将此 CSS 用于普通字体:

.bordered-titled-title {
  -fx-background-color: white;
  -fx-translate-y: -10; /* play around with this value when changing the title font to get a vertically centered title */
}

.bordered-titled-border {
  -fx-content-display: top;
  -fx-border-insets: 20 15 15 15;
  -fx-background-color: white;
  -fx-border-color: black;
  -fx-border-width: 2;
}

.bordered-titled-content {
  -fx-padding: 26 10 10 10;
}

使用这个 CSS,它现在看起来像这样:

enter image description here

更新:标题长于内容时的问题:

enter image description here有什么提示可以解决这个问题吗?

评论

0赞 Chris_D_Turk 2/14/2016
setContent() 方法有什么用?当 FxmlLoader 解析 fxml 文档时,它永远不会被调用!
0赞 CN1002 3/23/2016
我一直在寻找这个:) - 但它没有在 Scene building 中打开
0赞 Doctor Parameter 8/20/2016
@stefan您可以使用省略号字符串解决问题,但前提是您能找到一种方法来使标题的最大长度 Label 成为容器的长度。
0赞 Karol K 8/11/2019
在那之后的几年里;)也许像我这样的人,仍在寻找它。我使用了类似的解决方案,并从标签的左侧和右侧添加了一些边距。
46赞 Andriy Kryvtsun 6/18/2016 #4

我曾经用过.它看起来比使用 CSS 样式更一致。这是结果TitledPanesetCollapsible(false)

enter image description here

评论

5赞 golimar 11/25/2017
真的很简单方便
3赞 Doctor Parameter 8/20/2016 #5

下面是一个可以加载到 SceneBuilder 中的 FXML 文档,该文档具有类似的功能:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane style="-fx-border-insets: 8 0 0 0; -fx-background-color: #FFFFFF; -fx-border-color: black;">
    <children>
        <Label alignment="TOP_LEFT" layoutX="14.0" style="-fx-padding: 0 5; -fx-background-color: inherit;" text="Title" />
        <AnchorPane prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="1.0" AnchorPane.leftAnchor="1.0" AnchorPane.rightAnchor="1.0" AnchorPane.topAnchor="10.0" />
    </children>
</AnchorPane>

如果需要使标签文本/边框大小变大,则只需编辑子 AnchorPane 的 CSS 和 topAnchor 以及父 AnchorPane 的 -fx-border-insets 的第一个参数。

0赞 Mohamed Handosa 1/12/2017 #6

下面是基于 TitledPane 的 GroupBox 实现。它提供了三种方法来设置 GroupBox 的标题、内容和内容填充。

public final class GroupBox extends Parent {

    private StackPane _stackPane;
    private TitledPane _titledPane;

    public GroupBox() {
        _stackPane = new StackPane();
        _titledPane = new TitledPane();
        setContentPadding(new Insets(10));
        _titledPane.setCollapsible(false);
        _titledPane.setContent(_stackPane);
        super.getChildren().add(_titledPane);
    }

    public GroupBox(String title, Node content) {
        this();
        setText(title);
        setContent(content);
    }

    public GroupBox(String title, Node content, Insets contentPadding) {
        this(title, content);
        setContentPadding(contentPadding);
    }

    public void setText(String value) {
        _titledPane.setText(value);
    }

    public void setContent(Node node) {
        _stackPane.getChildren().add(node);
    }

    public void setContentPadding(Insets value) {
        _stackPane.setPadding(value);
    }
}