JavaFx:画一个类似摆动的低蚀刻边框可能吗?

JavaFx: drawing a swing-like lowered etched Border possible?

如何在 JavaFX 中绘制类似于在 Swing 标签中看到的内容的 Lower-Etched-Border

我研究了 Lowered-Etched-Border 的 JavaFX,但我没有找到任何有效的文档。我还测试了 InnerShadow 和其他效果,但这些效果不太适合。所以我创建了一个LEBLabelLabel的子类),类型为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 the Text-Alignment Properties.

示例基于 Region 扩展名和外部 CSS 文件。

如果需要,此实现允许边框包含任意可调整大小的内容(包括父布局窗格)。例如,您可以在 BorderPane 内放置一个包含内容的 StackPane 并使用 StackPane 的 "Optional Layout Constraints" 对齐内容并定义 BorderPane 内内容的边距(有关示例,请参见链接的 StackPane javadoc如何实现这一点)。

此外,边框本身的样式可以从外部 CSS 文件自定义,因此应该可以相对容易地复制任何 standard Swing borders(和其他边框样式)。

边框-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);
    }

}

相关问题

  • GroupBox / TitledBorder in JavaFX 2?