JavaFX如何在不更改线宽的情况下缩放Path的坐标? [英] JavaFX How do I scale the coordinates of a Path without altering the line width?

查看:75
本文介绍了JavaFX如何在不更改线宽的情况下缩放Path的坐标?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在研究具有缩放和平移功能的步骤折线图.由于我需要处理的数据量非常大,因此每次调用layoutPlotChildren()时,我都无法承受重新创建步线的整个路径的麻烦.所以我的想法是只创建一次path元素,然后在缩放和平移事件时对其进行转换.

I am currently working on a step line chart with a zoom and panning functionality. Since the amount of data I need to process is pretty large, i can not afford to recreate the whole path of the step line, every time layoutPlotChildren() is called. So my idea was to create the path element once and just transform it on zoom an pan events.

到目前为止,一切都按计划进行了,但是当我尝试扩展路径时,我遇到了一个大问题.由于Path类是从Shape继承的,因此在Graph上缩放不仅可以改变路径的坐标,而且可以改变其厚度.

So far everything worked out as planned, but i am having a big problem when I'm trying to scale the path. Since the Path class is inherited from Shape, scaling on the Graph not only transforms the coordinates of the path, but also alters its thickness.

我创建了一个最小的工作示例来说明这个问题:

I created a minimal working example to present the problem:

public class Sandbox extends Application
{

    @Override public void start(Stage primaryStage)
    {
        Path path = new Path();
        path.getElements().add(new MoveTo(0, 0));
        path.getElements().add(new LineTo(100, 0));
        path.getElements().add(new LineTo(100, 100));
        path.getElements().add(new LineTo(200, 100));

        path.setScaleY(3);

        Pane pane = new StackPane(path);

        Scene scene = new Scene(pane, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

如您所见,坐标按比例缩放,但是所有水平线的宽度是以前的三倍.我完全理解为什么会这样,但是我想不出任何防止线条变粗的可能性.您对我如何解决此问题同时又能确保可接受的性能有任何建议吗?

As you can see, the coordinates are scaled as intended, but all horizontal lines are three times as thick as before. I completely understand, why this is happening, but I can't think of any possibilities to prevent the thickening of the lines. Do you have any suggestions on how I could solve this problem while still assuring acceptable performance?

推荐答案

请注意,这不是Shape类的问题,而是实际缩放的问题:Node中的A缩放因子为x渲染每个距离的时间是未缩放Node的时间的x倍.这包括任何线条的粗细.

Note that this is not a problem of the Shape class, but a problem of what scaling actually does: A in Node scaled with a factor x every distance is rendered x times as long as in the unscaled Node. This includes the thickness of any lines.

但是,您可以通过将坐标乘以比例因子来修改路径元素的坐标:

You could however modify the coordinates of your path elements by multiplying the coordinates with the scale factor however:

// class for holing a pair of (x, y) properties with method for modifying the values based on scale
public static class PointScaler {

    private final DoubleProperty xProperty;
    private final DoubleProperty yProperty;
    private final double x0;
    private final double y0;

    public PointScaler(DoubleProperty xProperty, DoubleProperty yProperty) {
        this.xProperty = xProperty;
        this.yProperty = yProperty;

        // save untransformed values
        this.x0 = xProperty.get();
        this.y0 = yProperty.get();
    }

    public void setScale(double factor) {
        xProperty.set(factor * x0);
        yProperty.set(factor * y0);
    }

}

private double scaleFactor = 1;

@Override
public void start(Stage primaryStage) {
    Path path = new Path();
    MoveTo m0 = new MoveTo(0, 0);
    LineTo l0 = new LineTo(100, 0);
    LineTo l1 = new LineTo(100, 100);
    LineTo l2 = new LineTo(200, 100);
    path.getElements().addAll(m0, l0, l1, l2);

    // create list with scaler for each (x,y) pair in the path elements
    List<PointScaler> scalers = new ArrayList<>();
    scalers.add(new PointScaler(m0.xProperty(), m0.yProperty()));
    scalers.add(new PointScaler(l0.xProperty(), l0.yProperty()));
    scalers.add(new PointScaler(l1.xProperty(), l1.yProperty()));
    scalers.add(new PointScaler(l2.xProperty(), l2.yProperty()));

    Pane pane = new StackPane(path);

    Scene scene = new Scene(pane, 800, 600);

    // change scale on click of mouse buttons
    scene.setOnMouseClicked(evt -> {
        if (evt.getButton() == MouseButton.PRIMARY) {
            scaleFactor *= 1.2;
        } else if (evt.getButton() == MouseButton.SECONDARY) {
            scaleFactor /= 1.2;
        } else {
            return;
        }
        // apply scale to path points
        for (PointScaler scaler : scalers) {
            scaler.setScale(scaleFactor);
        }
    });

    primaryStage.setScene(scene);
    primaryStage.show();
}

请注意,setScale方法使x和y的比例保持相同,但是修改该方法以适用于不同的转换并不难.请注意,某些PathElement(例如CubicCurveToQuadCurveTo)需要的不仅是单个PointScaler实例.

Note that the setScale method keeps x and y scale the same but it shouldn't be too hard modify the method to work for different transforms. Note that some PathElements like CubicCurveTo and QuadCurveTo require more than a single PointScaler instance.

这篇关于JavaFX如何在不更改线宽的情况下缩放Path的坐标?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆