Reputation: 1715
How can I draw a Lower-Etched-Border
in JavaFX similar to what is seen in a Swing label?
Upvotes: 2
Views: 2099
Reputation: 159291
Sample based upon a Region extension coupled with an external CSS file.
This implementation allows the border to encompass arbitrary resizable content (including parent layout panes) if required. For example, you could place a StackPane containing content inside the BorderPane and use the "Optional Layout Constraints" of the StackPane to align the content and define margins for the content within the BorderPane (see the linked StackPane javadoc for an example of how to accomplish this).
Additionally, the style of the border itself can be customized from the external CSS file, so it should be possible to replicate any of the standard Swing borders (and other border styles) relatively easily.
border-pane.css
.border-pane {
-fx-border-base: gray;
-fx-border-shadow: white;
-fx-light-border: derive(-fx-border-base, 25%);
-fx-border-color: -fx-light-border -fx-border-base -fx-border-base -fx-light-border;
-fx-border-insets: 0 1 1 0;
-fx-background-color: -fx-border-shadow, -fx-background;
-fx-background-insets: 1 0 0 1, 2;
-fx-padding: 2;
}
LoweredEtchedBorderLabelBackgroundDemo.java
import javafx.application.Application;
import javafx.geometry.*;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class LoweredEtchedBorderDemo extends Application {
@Override
public void start(Stage stage) {
Label label = new Label("Testing");
label.setPadding(new Insets(10));
// uncomment to see the area that the content node is taking up within the border.
//label.setStyle("-fx-background-color: palegreen;");
BorderPane borderPane = new BorderPane(new StackPane(label));
// uncomment these two lines if you would like the border to resize to fit available space.
borderPane.setMinSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE);
borderPane.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE);
VBox layout = new VBox(borderPane);
layout.setPadding(new Insets( 10));
layout.setStyle("-fx-base: lightgrey;");
VBox.setVgrow(borderPane, Priority.ALWAYS);
Scene scene = new Scene(layout);
stage.setScene(scene);
stage.show();
}
private class BorderPane extends Region {
// clip the bordered content within the bordered area.
Rectangle clipRect = new Rectangle(getWidth(), getHeight());
public BorderPane(Node content) {
super();
getChildren().add(content);
getStylesheets().add(getClass().getResource(
"border-pane.css"
).toExternalForm());
getStyleClass().add("border-pane");
// by default size the border to the preferred size of the content.
setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
content.setClip(clipRect);
}
@Override protected void layoutChildren() {
final double width = getWidth();
double height = getHeight();
double top = getInsets().getTop();
double right = getInsets().getRight();
double left = getInsets().getLeft();
double bottom = getInsets().getBottom();
double contentWidth = width - left - right;
double contentHeight = height - top - bottom;
Node child = getManagedChildren().get(0);
layoutInArea(child, left, top,
contentWidth, contentHeight,
0, null,
HPos.LEFT,
VPos.TOP);
clipRect.setWidth(contentWidth);
clipRect.setHeight(contentHeight);
}
}
public static void main(String[] args) {
launch(args);
}
}
Related Question
Upvotes: 2
Reputation: 2058
I researched for Lowered-Etched-Border
for JavaFX but i didn't found any effective document. I also tested InnerShadow
and other effects and those are not good fit for that. So i created a LEBLabel
(subclass of Label
) with that type of border-style.
public class LoweredEtchedBorderLabelDemo extends Application {
@Override
public void start(Stage primaryStage) {
LEBLabel text = new LEBLabel("Testing", 200, 30);
StackPane root = new StackPane();
root.getChildren().add(text);
root.setStyle("-fx-background-color:lightgrey");
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Lowered-Etched-Border Demo");
primaryStage.setScene(scene);
primaryStage.show();
}
//Lowered Etched Borderd Label
private class LEBLabel extends Label {
private HBox[] borders = new HBox[3];
private String border_styles[] = {"-fx-border-width:0 1 1 0; -fx-border-color: white",
"-fx-border-width:1; -fx-border-color:grey",
"-fx-border-width:1 0 0 1; -fx-border-color:white"};
public LEBLabel(String text, double width, double height) {
super(text);
for(int i = 0; i < borders.length; i++) {
borders[i] = new HBox();
borders[i].setStyle(border_styles[i]);
//decrement of border-size for inner-border, prevents from the overlapping of border
borders[i].setMaxSize(width - (1.5 *i), height - (1.5 * i));
borders[i].setMinSize(width - (1.5 *i), height - (1.5 * i));
borders[i].setSpacing(0);
}
this.setContentDisplay(ContentDisplay.CENTER);
this.borders[1].getChildren().add(borders[2]);
this.borders[0].getChildren().add(borders[1]);
this.setGraphic(borders[0]);
}
}
public static void main(String[] args) {
launch(args);
}
}
Note : This
LEBLabel
displays the text on Center-Side only so it ignores theText-Alignment Properties
.
Upvotes: 3