Issue
I am developing a application where I need some widgets to wrap up inside a panel. And I want to put a border around it. I am a swt programmer where in composite I can pass swt.border to put border. But how to do that in JavaFX. Any help on this is appreciated.
CODE:
Label Center=new Label();
Center.setText("Center Frequency");
GridPane.setConstraints(Center, 0, 0);
tb1[i].getChildren().add(Center);
TextField text=new TextField();
GridPane.setConstraints(text, 1, 0);
tb1[i].getChildren().add(text);
Label chiprate=new Label();
chiprate.setText("Chiprate");
GridPane.setConstraints(chiprate, 0, 1);
tb1[i].getChildren().add(chiprate);
TextField chip=new TextField();
GridPane.setConstraints(chip, 1, 1);
tb1[i].getChildren().add(chip);
Label frequency=new Label();
frequency.setText("Frequency deviation");
GridPane.setConstraints(frequency, 0, 2);
tb1[i].getChildren().add(frequency);
TextField frequencydeviation=new TextField();
GridPane.setConstraints(frequencydeviation, 1, 2);
tb1[i].getChildren().add(frequencydeviation);
Label outputLabel=new Label();
outputLabel.setText("Output Power");
GridPane.setConstraints(outputLabel, 0, 3);
tb1[i].getChildren().add(outputLabel);
TextField output=new TextField();
GridPane.setConstraints(output, 1, 3);
tb1[i].getChildren().add(output);
Solution
I create a BorderedTitledPane
class which places a titled border around content.
If you don't need to have a title placing a border around things is even easier - just set the the css border parameters on a region (e.g. -fx-border-color: black;
).
Here is a complete executable sample.
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
/** Places content in a bordered pane with a title. */
public class BorderedTitledPane extends StackPane {
private StringProperty title = new SimpleStringProperty();
private ObjectProperty<Node> graphic = new SimpleObjectProperty<>();
private ObjectProperty<Node> content = new SimpleObjectProperty<>();
private ObjectProperty<Pos> titleAlignment = new SimpleObjectProperty<>();
// todo other than TOP_LEFT other alignments aren't really supported correctly, due to translation fudge for indentation of the title label in css => best to implement layoutChildren and handle layout there.
// todo work out how to make content the default node for fxml so you don't need to write a <content></content> tag.
public BorderedTitledPane() {
this("", null);
}
public BorderedTitledPane(String titleString, Node contentNode) {
final Label titleLabel = new Label();
titleLabel.textProperty().bind(Bindings.concat(title, " "));
titleLabel.getStyleClass().add("bordered-titled-title");
titleLabel.graphicProperty().bind(graphic);
titleAlignment.addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
StackPane.setAlignment(titleLabel, titleAlignment.get());
}
});
final StackPane contentPane = new StackPane();
getStyleClass().add("bordered-titled-border");
getChildren().addAll(titleLabel, contentPane);
content.addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
if (content.get() == null) {
contentPane.getChildren().clear();
} else {
if (!content.get().getStyleClass().contains("bordered-titled-content")) {
content.get().getStyleClass().add("bordered-titled-content"); // todo would be nice to remove this style class when it is no longer required.
}
contentPane.getChildren().setAll(content.get());
}
}
});
titleAlignment.set(Pos.TOP_LEFT);
this.title.set(titleString);
this.content.set(contentNode);
}
public String getTitle() {
return title.get();
}
public StringProperty getTitleStringProperty() {
return title;
}
public void setTitle(String title) {
this.title.set(title);
}
public Pos getTitleAlignment() {
return titleAlignment.get();
}
public ObjectProperty<Pos> titleAlignmentProperty() {
return titleAlignment;
}
public void setTitleAlignment(Pos titleAlignment) {
this.titleAlignment.set(titleAlignment);
}
public Node getContent() {
return content.get();
}
public ObjectProperty<Node> contentProperty() {
return content;
}
public void setContent(Node content) {
this.content.set(content);
}
public Node getGraphic() {
return graphic.get();
}
public ObjectProperty<Node> graphicProperty() {
return graphic;
}
public void setGraphic(Node graphic) {
this.graphic.set(graphic);
}
}
Related CSS.
.bordered-titled-title {
-fx-translate-x: 8;
-fx-translate-y: -10;
-fx-padding: 0 0 0 4;
-fx-background-color: -fx-background;
}
.bordered-titled-border {
-fx-content-display: top;
-fx-border-insets: 2 0 0 0;
-fx-border-color: -fx-text-box-border;
-fx-border-width: 2;
}
.bordered-titled-content {
-fx-padding: 18 5 5 5;
}
Answered By - jewelsea
Answer Checked By - Timothy Miller (JavaFixing Admin)