【问题标题】:How to create a background grid如何创建背景网格
【发布时间】:2015-05-06 09:15:54
【问题描述】:

我想创建一个网格作为我的 JavaFX 应用程序的背景。我目前的解决方案是在画布上绘制一个矩形,从中创建一个图像图案并将其设置为填充。

问题:有没有更好的方法来解决这个问题,最好是通过 CSS?

当前版本:

public class BackgroundGrid extends Application {

    double gridSize = 20;

    @Override
    public void start(Stage primaryStage) {

        Scene scene = new Scene(new Group(), 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();

        scene.setFill(createGridPattern());

    }

    public ImagePattern createGridPattern() {

        double w = gridSize;
        double h = gridSize;

        Canvas canvas = new Canvas(w, h);
        GraphicsContext gc = canvas.getGraphicsContext2D();

        gc.setStroke(Color.BLACK);
        gc.setFill(Color.LIGHTGRAY.deriveColor(1, 1, 1, 0.2));
        gc.fillRect(0, 0, w, h);
        gc.strokeRect(0, 0, w, h);

        Image image = canvas.snapshot(new SnapshotParameters(), null);
        ImagePattern pattern = new ImagePattern(image, 0, 0, w, h, false);

        return pattern;

    }

    public static void main(String[] args) {
        launch(args);
    }
}

非常感谢!

编辑:为了获得清晰的网格线,只需使用

gc.strokeRect(0.5, 0.5, w, h);

我认为这在 CSS 中是不可行的,不是吗?

【问题讨论】:

  • 谢谢,我已经看到了。我的意思是如果可以只用 css 做所有事情,而不是如何应用自定义 css。顺便说一句,你认为什么更快?用图案的解决方案还是用线条绘制的解决方案?我不确定,因为我不知道内部发生了什么。
  • 我不知道哪个更快,但如果我不得不猜测,我会说这取决于你调整网格的大小。

标签: css background javafx


【解决方案1】:

您也可以使用 CSS 来实现。这就是你所需要的:

.root {
    -fx-background-color: #D3D3D333,
        linear-gradient(from 0.5px 0.0px to 10.5px  0.0px, repeat, black 5%, transparent 5%),
        linear-gradient(from 0.0px 0.5px to  0.0px 10.5px, repeat, black 5%, transparent 5%);
}

0.5px 偏移解决了从 0px 设置为 10px 时的一些错误行为,并且某些线条以两个像素而不是一个像素呈现:

【讨论】:

  • 在 Java 13 / openjfx 13 / macOS 10.14.6 上看起来没有 0.5 个偏移量。
  • 此外,移除 0.5 个偏移量可以使网格线与在整数坐标上沿网格线绘制的 Line 形状对象重合。
  • 这个 css 技巧在缩放时效果很差,尤其是在较小的比例下。在画布上手动绘制网格具有与 css 相同的缩放伪影问题。在未缩放的画布上绘制网格并根据需要重新绘制它可以避免缩放伪影。
  • @silvalli 感谢您的意见,但现在(6 岁)似乎没有必要复习这个旧答案。发布您自己的答案会更好,您可以在其中详细说明 OP 要求的 CSS 解决方案的局限性,也许其他人会更喜欢它。
【解决方案2】:

这是从旧的Oracle forum post 复制的答案。

基于 GridPane 的方法

一些方法(基于GridPane 布局):

  1. 单个单元格的样式边框(并确保它们填充 他们的整个网格位置)或
  2. 风格整体背景 网格在填充整个网格的单元格之间留下间隙 位置如下图或
  3. 用线条添加新的网格节点,然后 为添加的线条设置样式。

我为下面的代码选择了方法 2(设置网格背景样式)。该示例使用内联 CSS 样式(因为我很懒),但它可以与外部 CSS 样式表一起工作(并且更好)来设置网格样式。

import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

public class GridPaneStyle extends Application {
    @Override
    public void start(final Stage stage) {
        // create a grid with some sample data.
        GridPane grid = new GridPane();
        grid.addRow(0, new Label("1"), new Label("2"), new Label("3"));
        grid.addRow(1, new Label("A"), new Label("B"), new Label("C"));

        // make all of the Controls and Panes inside the grid fill their grid cell, 
        // align them in the center and give them a filled background.
        // you could also place each of them in their own centered StackPane with 
        // a styled background to achieve the same effect.
        for (Node n : grid.getChildren()) {
            if (n instanceof Control) {
                Control control = (Control) n;
                control.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
                control.setStyle("-fx-background-color: cornsilk; -fx-alignment: center;");
            }
            if (n instanceof Pane) {
                Pane pane = (Pane) n;
                pane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
                pane.setStyle("-fx-background-color: cornsilk; -fx-alignment: center;");
            }
        }

        // style the grid so that it has a background and gaps around the grid and between the 
        // grid cells so that the background will show through as grid lines.
        grid.setStyle("-fx-background-color: palegreen; -fx-padding: 2; -fx-hgap: 2; -fx-vgap: 2;");
        // turn layout pixel snapping off on the grid so that grid lines will be an even width.
        grid.setSnapToPixel(false);

        // set some constraints so that the grid will fill the available area.
        ColumnConstraints oneThird = new ColumnConstraints();
        oneThird.setPercentWidth(100 / 3.0);
        oneThird.setHalignment(HPos.CENTER);
        grid.getColumnConstraints().addAll(oneThird, oneThird, oneThird);
        RowConstraints oneHalf = new RowConstraints();
        oneHalf.setPercentHeight(100 / 2.0);
        oneHalf.setValignment(VPos.CENTER);
        grid.getRowConstraints().addAll(oneHalf, oneHalf);

        // layout the scene in a stackpane with some padding so that the grid is centered 
        // and it is easy to see the outer grid lines.
        StackPane layout = new StackPane();
        layout.setStyle("-fx-background-color: whitesmoke; -fx-padding: 10;");
        layout.getChildren().addAll(grid);
        stage.setScene(new Scene(layout, 600, 400));
        stage.show();

        // can be uncommented to show the grid lines for debugging purposes, but not particularly useful for styling purposes.
        //grid.setGridLinesVisible(true);
    }

    public static void main(String[] args) {
        launch();
    }
}

基于画布的替代方法

另请参阅 FXExperience 博客文章Resizable Grid using Canvas

【讨论】:

    【解决方案3】:

    获得真正清晰的网格线的建议并不适用于所有系统。在 Retina 显示器上,您必须使用 0.5 的线宽,然后从整数线坐标偏移 0.25。因此,在实践中,您必须确定您的应用程序在哪个系统上运行,然后使用不同的线宽和偏移量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      • 2018-05-13
      • 1970-01-01
      相关资源
      最近更新 更多