【问题标题】:JavaFX Stretch Canvas To DimensionsJavaFX 将画布拉伸到尺寸
【发布时间】:2021-06-06 07:07:30
【问题描述】:

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

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 示例中,我想将画布(GraphicsContext)视为固定大小的像素缓冲区。我想将每一帧拉伸或收缩到窗口尺寸(或我指定的任何尺寸)。我见过的许多例子似乎增加了画布节点本身的宽度和高度。我想拉伸画布的 content,如果有意义的话,而不是画布节点本身。

对于 JavaFX,是否有等效于 StretchDIBits 的方法?

【问题讨论】:

  • @Slaw 如果我采用scale_x = canvas_fixed_width / window_width,我将如何获得当前的窗口宽度?
  • 但这有意义吗?画布中的任何图形都会看起来扭曲。这就是你想要的吗?
  • @mipa 我知道如果不处理纵横比,它会看起来失真(适合调试)如果 JavaFX 具有我正在寻找的等效功能(这在图形库中很常见,例如 Windows API、Xlib、 AppKit)然后处理纵横比很简单。
  • @Slaw 我在AnimationTimer handle() 中的循环调用gc.scale(1280 / scene.getWidth(), 720 / scene.getHeight()); 这在初始打开时有效,但在调整大小时会出现问题。我尝试设置canvas,但它在增加时向内推内容,即 0,0 移动到中心并在缩小时放大
  • 您应该问问自己,Canvas 是否是正确的方法。在我看来,场景图似乎是更好的选择。人们不应该总是在不同环境之间寻找一对一的概念替换。

标签: java javafx canvas rendering


【解决方案1】:

我不相信有一个内置的方法可以调用来做你想做的事。但是您可以缩放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();
  }
}

【讨论】:

  • 这似乎在最大化时会导致文本模糊?
  • 这并不让我感到惊讶,但我不知道如何解决它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多