3

我想知道 JavaFX 2.1 中线条的确切宽度。

创建从点 (10;10) 到点 (20;10) 的直线的预期宽度应为 10 像素。当读取线的宽度时,会返回 11px 的值。当开始附加的示例并制作屏幕截图时,您会看到 - 在更高的缩放级别 - 线条的宽度为 12 像素,高度为 2 像素。

使用 aLineBuilder没有任何区别。我试图应用不同的方法StrokeType但没有成功。

创建一个边长为 10 的正方形会返回 10px 的预期宽度。

  1. 为什么line.getBoundsInLocal().getWidth()返回的值与我在渲染结果(屏幕截图)中看到的不同?
  2. 为什么在创建线和多边形时宽度会有所不同?

例子:

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polygon;
import javafx.stage.Stage;

public class ShapeWidthDemo extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Group root = new Group();

        int startX = 10;
        int startY = 10;
        int length = 10;

        Line line = new Line(startX, startY, startX + length, startY);
        System.out.println("line width: " + line.getBoundsInLocal().getWidth());
        //->line width: 11.0
        System.out.println("line height: " + line.getBoundsInLocal().getHeight());
        //->line height: 1.0
        root.getChildren().add(line);

        int startY2 = startY + 2;

        Polygon polygon = new Polygon(
            startX, startY2,
            startX + 10, startY2, 
            startX + 10, startY2 + 10, 
            startX, startY2 + 10);
        System.out.println("polygon width: " + polygon.getBoundsInLocal().getWidth());
        //->polygon width: 10.0
        System.out.println("polygon height: " + polygon.getBoundsInLocal().getHeight());
        //->polygon height: 10.0
        root.getChildren().add(polygon);

        stage.setScene(new Scene(root, 100, 100));
        stage.show();
    }

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

2 回答 2

2

1) 线的端点由 控制StrokeLineCap
因此,使用默认笔划宽度,您可以通过

line.setStrokeType(StrokeType.CENTERED);
line.setStrokeLineCap(StrokeLineCap.BUTT);
... that the line has a width of 12px and a height of 2px.

StrokeType.OUTSIDE 如果应用AND NOT ,您可以获得这些值StrokeLineCap.BUTT。然而,即使更改笔触属性,高度仍保持在 2px。那很奇怪..

2) 因为多边形的笔画值默认为NULL。通过设置它就像polygon.setStroke(Color.RED);笔画将呈现。

于 2012-08-09T11:24:47.597 回答
1

将线本身想象成没有任何表面积,它是无限细的。线条的唯一尺寸来自笔划。

当 StrokeType 为 CENTERED并且StrokeLineCap 为SQUARE(默认值)时,线条所占据的区域来自于在所有方向上均匀地围绕线条应用一半的笔划宽度。

在您的示例中,您在整数坐标处绘制一条笔划为 1 的水平线。JavaFX坐标系统使得整数角映射到像素之间的线。当您显示一条具有整数坐标的水平线时,该线本身穿过该线任一侧的两个垂直像素的一半,并最终成为一条灰色阴影的抗锯齿线,而不是一条只有一个垂直像素的黑色线。此外,在线条末端应用 SQUARE 的 StrokeLineCap 意味着笔划超出线条端点的一半笔划宽度。这最终对线末端两侧的两对像素中的每个像素的四分之一进行着色。

通过将线条的坐标偏移半个像素,可以绘制线条,使其遮蔽单行垂直像素,因为现在线条沿着每个像素的中间下降并且线条笔触延伸到顶部和每个像素的底部边缘。此外,将线帽设置为对接而不是方形意味着线的阴影区域不会超出线的末端。

这是一些示例代码来演示这一点。在示例中,只有最后一行完全遮住了 10 个像素,仅此而已。它也是唯一一条宽度为 10 且在其边界框中具有整数坐标的线。

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.shape.Line;
import javafx.scene.shape.StrokeLineCap;
import javafx.stage.Stage;

public class LineBounds extends Application {
  public static void main(String[] args) { launch(args); }
  @Override public void start(Stage stage) throws Exception {
    double startX = 10;
    double startY = 10;
    double length = 10;

    Line lineSpanningPixelsSquareEnd = new Line(startX, startY, startX + length, startY);
    System.out.println("lineSpanningPixels (square) bounding box: " + lineSpanningPixelsSquareEnd.getBoundsInLocal());

    startX = 10;
    startY = 20;
    length = 10;

    Line lineSpanningPixelsButtEnd = new Line(startX, startY, startX + length, startY);
    lineSpanningPixelsButtEnd.setStrokeLineCap(StrokeLineCap.BUTT);
    System.out.println("lineSpanningPixels (butt) bounding box:   " + lineSpanningPixelsButtEnd.getBoundsInLocal());

    startX = 10;
    startY = 29.5;
    length = 10;

    Line lineOnPixelsSquareEnd = new Line(startX, startY, startX + length, startY);
    System.out.println("lineOnPixels (square) bounding box:       " + lineOnPixelsSquareEnd.getBoundsInLocal());

    startX = 10;
    startY = 39.5;
    length = 10;

    Line lineOnPixelsButtEnd = new Line(startX, startY, startX + length, startY);
    lineOnPixelsButtEnd.setStrokeLineCap(StrokeLineCap.BUTT);
    System.out.println("lineOnPixels (butt) bounding box:         " + lineOnPixelsButtEnd.getBoundsInLocal());

    stage.setScene(
      new Scene(
        new Group(
          lineSpanningPixelsSquareEnd, lineSpanningPixelsButtEnd, lineOnPixelsSquareEnd, lineOnPixelsButtEnd
        ), 100, 100
      )
    );
    stage.show();
  }
}

示例程序的输出是:

lineSpanningPixels (square) bounding box: BoundingBox [minX:9.5, minY:9.5, minZ:0.0, width:11.0, height:1.0, depth:0.0, maxX:20.5, maxY:10.5, maxZ:0.0]
lineSpanningPixels (butt) bounding box:   BoundingBox [minX:10.0, minY:19.5, minZ:0.0, width:10.0, height:1.0, depth:0.0, maxX:20.0, maxY:20.5, maxZ:0.0]
lineOnPixels (square) bounding box:       BoundingBox [minX:9.5, minY:29.0, minZ:0.0, width:11.0, height:1.0, depth:0.0, maxX:20.5, maxY:30.0, maxZ:0.0]
lineOnPixels (butt) bounding box:         BoundingBox [minX:10.0, minY:39.0, minZ:0.0, width:10.0, height:1.0, depth:0.0, maxX:20.0, maxY:40.0, maxZ:0.0]

行边界示例程序输出

于 2012-08-10T00:19:42.000 回答