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

时间:2017-02-18 22:46:34

标签: java javafx javafx-8 border

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

2 个答案:

答案 0 :(得分:3)

我为JavaFX研究了Lowered-Etched-Border,但我没有找到任何有效的文档。我还测试了InnerShadow和其他效果,但那些效果并不合适。所以我用这种边框样式创建了LEBLabelLabel的子类)。

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

}
  

注意:此LEBLabel仅在中心一侧显示文字,因此忽略了Text-Alignment Properties

答案 1 :(得分:2)

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

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

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

Testing

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

}

相关问题