如何在 JavaFX 2.2 中绘制清晰、不透明的细线?

Posted

技术标签:

【中文标题】如何在 JavaFX 2.2 中绘制清晰、不透明的细线?【英文标题】:How to draw a crisp, opaque hairline in JavaFX 2.2? 【发布时间】:2012-08-06 20:16:21 【问题描述】:

在 JavaFX 2.2 中绘制清晰、不透明的细线的最佳方法是什么?

文档说,strokeWidth0.0d 将是一条细线,但它根本不可见。值> 0.0d and <1.0d 显示的线条非常好,但也没有表现出不透明的行为。当一条线切割另一条线时,相交点比线的其余部分轻(我希望这种行为来自具有一定透明度的线)。最后,1.0d 绘制了一条宽度为几个像素的白线。

这是我的测试代码:

LineBuilder.create().startX(i*gridSize).startY(0).endX(i*gridSize).endY(height).smooth(false).stroke(Color.WHITE).strokeWidth(0.5d).fill(Color.WHITE).build();           

【问题讨论】:

【参考方案1】:

您可以使用Region 子类,例如将Pane 用于您的Parent,并将snapToPixel 设置为true。

另外,请参阅坐标系上的Node 文档。

在设备像素级别,整数坐标映射到角落 像素和像素中心之间出现裂缝 整数像素位置之间的中点。因为所有坐标 值用浮点数指定,坐标可以 精确指向这些角(当浮点值有 精确的整数值)或像素上的任何位置。例如,一个 (0.5, 0.5) 的坐标将指向左上角的中心 舞台上的像素。类似地,一个位于 (0, 0) 的矩形,其尺寸为 10 x 10 将跨越左上角的左上角 舞台上的像素到舞台上第 10 个像素的右下角 第 10 条扫描线。里面最后一个像素的像素中心 矩形将位于坐标 (9.5, 9.5)。

另请参阅Shape 文档:

大多数节点往往只应用整数转换,并且 它们通常也使用整数坐标定义。为了 在这种常见情况下,具有直线边缘的形状填充往往是 清晰,因为它们与落在像素之间的裂缝对齐 整数设备坐标,因此往往自然覆盖整个 像素。另一方面,抚摸这些相同的形状通常会导致 到模糊的轮廓,因为默认的描边属性同时指定了 默认笔画宽度是 1.0 坐标,通常映射到 正好 1 个设备像素,并且笔划应该跨越 形状的边界,在边界的两侧下降一半。自从 许多常见形状的边框往往直接落在整数上 坐标和那些整数坐标通常精确映射到 整数设备位置,边界往往会导致 50% 的覆盖率 在边界两侧的像素行和列上 形状而不是 100% 覆盖一个或另一个。因此,填充可能 通常是清脆的,但笔画通常是模糊的。

避免这些模糊轮廓的两种常见解决方案是使用更宽的 完全覆盖更多像素的笔画 - 通常是笔画宽度 如果没有有效的比例变换,2.0 的 2.0 将实现这一点 - 或指定 StrokeType.INSIDE 或 StrokeType.OUTSIDE 笔划样式 - 将默认的单个单位笔划偏向 内部或外部的完整像素行或列之一 形状的边框。

因此,如果您将节点留在没有 snapToPixel 的组或区域中,您可以按照 Shape 文档中的上述说明进行操作。

这里是一些示例代码:

import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.LineBuilder;
import javafx.scene.shape.StrokeType;
import javafx.scene.text.Text;
import javafx.stage.Stage;

/** http://***.com/questions/11886230/how-to-draw-a-crisp-opaque-hairline-in-javafx-2-2 */
public class LineWidths extends Application 
  public static void main(String[] args)  launch(args); 

  @Override public void start(Stage stage) 
    Line fuzzyline = LineBuilder.create()
        .startX(5).startY(50)
        .endX(90).endY(50)
        .stroke(Color.BLACK).strokeWidth(1)
      .build();
    Line hairline = LineBuilder.create()
        .startX(4.5).startY(99.5)
        .endX(89.5).endY(99.5)
        .stroke(Color.BLACK).strokeWidth(1)
      .build();
    Line fatline = LineBuilder.create()
        .startX(5).startY(150)
        .endX(90).endY(150)
        .stroke(Color.BLACK).strokeWidth(1).strokeType(StrokeType.OUTSIDE)
      .build();
    Pane snappedPane = new Pane();
    Line insideline = LineBuilder.create()
        .startX(5).startY(25)
        .endX(90).endY(25)
        .stroke(Color.BLACK).strokeWidth(1)
      .build();
    snappedPane.setSnapToPixel(true);
    snappedPane.getChildren().add(insideline);
    snappedPane.setPrefSize(100, 50);
    snappedPane.relocate(-0.5, 174.5);

    stage.setScene(
      new Scene(
        new Group(
          fuzzyline, hairline, fatline, snappedPane,
          new Text(10, 40, "fuzzyline"),  
          new Text(10, 90, "hairline"),  
          new Text(10, 140, "fatline"),  
          new Text(10, 190, "snappedPane")
        ), 100, 250
      )
    );
    stage.show();
  

【讨论】:

另见相关问题:What are a line's exact dimensions in JavaFX 2?

以上是关于如何在 JavaFX 2.2 中绘制清晰、不透明的细线?的主要内容,如果未能解决你的问题,请参考以下文章

如何在javafx中制作透明的场景和舞台?

为啥 javafx 会破坏我的半透明游标?

如何在 JavaFX 中创建具有透明背景的启动画面

cesium如何改变地图gamma某一块区域的透明度

如何在 JavaFx 2.2 中嵌入 .ttf 字体?

javafx如何设置文本框TextArea背景色为透明