JavaFX 拉伸 Canvas 到维度

JavaFX Stretch Canvas To Dimensions

在我的 C++ Windows 程序中,我直接绘制到固定像素缓冲区 (u32 *) 并拉伸它以适应 window 尺寸:

StretchDIBits(device_context, 
              0, 0, window_width, window_height,
              src_x, src_y, src_width, src_height,
              src_memory, src_info,
              DIB_RGB_COLORS, SRCCOPY);

我是 JavaFX 的新手。 在 JavaFX 中说我有:

@Override
public void
start(Stage primary_stage) throws Exception
{
   Group root = new Group();
   Scene scene = new Scene(root);
   primary_stage.setScene(scene);
   Canvas canvas = new Canvas(1280, 720);
   root.getChildren().add(canvas);
   GraphicsContext gc = canvas.getGraphicsContext2D();
}

我想在 Windows 示例中将 canvas(它是 GraphicsContext)视为固定大小的像素缓冲区。我想将每一帧拉伸或缩小到 window 尺寸(或我指定的任何尺寸)。我看到的许多例子似乎增加了 canvas 节点本身的宽度和高度。如果有意义的话,我想拉伸 canvas 的 content,而不是 canvas 节点本身。

JavaFX 是否有等同于 StretchDIBits 的工具?

我不相信有一个内置方法可以调用来做你想做的事。但是您可以缩放 Canvas 以填充可用的 space。随着 canvas 的父项调整大小时,您需要不断更新比例因子。这可能最好通过自定义布局来实现。例如:

import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.Region;

public class AutoScalingCanvas extends Region {

  private final Canvas canvas;

  public AutoScalingCanvas(double canvasWidth, double canvasHeight) {
    this.canvas = new Canvas(canvasWidth, canvasHeight);
    getChildren().add(canvas);
  }

  public GraphicsContext getGraphicsContext2D() {
    return canvas.getGraphicsContext2D();
  }

  @Override
  protected void layoutChildren() {
    double x = getInsets().getLeft();
    double y = getInsets().getTop();
    double w = getWidth() - getInsets().getRight() - x;
    double h = getHeight() - getInsets().getBottom() - y;

    // preserve aspect ratio while also staying within the available space
    double sf = Math.min(w / canvas.getWidth(), h / canvas.getHeight());
    canvas.setScaleX(sf);
    canvas.setScaleY(sf);

    positionInArea(canvas, x, y, w, h, -1, HPos.CENTER, VPos.CENTER);
  }
}

下面是一个使用上面的例子:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Main extends Application {

  @Override
  public void start(Stage primaryStage) {
    AutoScalingCanvas canvas = new AutoScalingCanvas(500, 300);
    canvas.getGraphicsContext2D().fillOval(200, 100, 100, 100);
    canvas.getGraphicsContext2D().setLineWidth(5);
    canvas.getGraphicsContext2D().setStroke(Color.RED);
    canvas.getGraphicsContext2D().strokeRect(0, 0, 500, 300);

    primaryStage.setScene(new Scene(canvas));
    primaryStage.show();
  }
}