Каковы точные размеры линии в JavaFX 2?
Меня интересует точная ширина линии в JavaFX 2.1.
Создание прямой линии, начинающейся в точке (10; 10) и заканчивающейся в точке (20;10), должно иметь ожидаемую ширину 10px. При считывании ширины линии возвращается значение 11px.
При запуске прилагаемого примера и создании скриншота вы увидите - при более высоком уровне масштабирования - линию шириной 12 пикселей и высотой 2 пикселя.
Использование LineBuilder не имеет никакого значения. Я попытался применить другое событие StrokeType без успеха.
Создание квадрата со стороной длиной 10 возвращает ожидаемую ширину 10px.
- Почему
line.getBoundsInLocal().getWidth()возвращает значения, отличные от тех, которые я вижу в отрисованном результате (скриншот)? - Почему существует разница в ширине при создании линий и полигонов?
Пример:
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);
}
}
2 ответов:
Представьте себе, что сама линия не имеет никакой поверхности, она бесконечно тонка. Единственные размеры для линии происходят от штриха.
Когда StrokeType является центрированным и StrokeLineCap является квадратным (значения по умолчанию), то площадь, занимаемая линией, получается из равномерного применения половины ширины штриха вокруг линии во всех направлениях.
В вашем примере вы рисуете горизонтальную линию с штрихом 1 в целочисленной координате. Система координат JavaFX такова, что целочисленные углы соответствуют линиям между пикселями. При отображении горизонтальной линии с целочисленными координатами сама линия пересекает половину двух вертикальных пикселей по обе стороны от линии и заканчивается как серая затененная сглаженная линия, а не черная линия, затеняющая только один вертикальный пиксель. Кроме того, 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]
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и нетStrokeLineCap.BUTTприменяются. Однако высота остается в 2px даже при изменении атрибутов штриха. Это странно..2) его из-за обводки полигона значение по умолчанию равно NULL. Установив его как
polygon.setStroke(Color.RED);, инсульт будет визуализироваться.

Comments