CubicCurve JavaFX [英] CubicCurve JavaFX

查看:158
本文介绍了CubicCurve JavaFX的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在JavaFX中使用CubicCurve很困难。如何画一个例子:y = x ^ 3?绘制曲线的机制看起来非常笨拙。

也可以将曲线的一个端点连接到另一个节点,所以当该节点的位置发生变化时曲线适用于它?



谢谢。

解决方案

我认为JavaFX中的CubicCurves并不像你认为的那样工作。 JavaFX CubicCurve是一个贝塞尔曲线,与三次多项式完全不同y = x ^ 3你通常在高中数学中遇到过。您从来不想知道的关于贝塞尔曲线的所有内容都是此处



贝塞尔曲线通常用于在计算机图形中生成平滑曲线。它们由起点和终点以及一组控制点来定义曲线。你可以用一个交互式的例子来展示它是如何工作的,在这个例子中你拖动开始点,结束点和控制点来形成不同的曲线。 >如何绘制一个例子:y = x ^ 3?

虽然有可能求解Bezier方程以减少到一个多项式,例如y = x ^ 3,你可能想在 math.stackexchange.com 上提出这个问题,那里的数学家的素质是比例如我会高得多。



另一种方法是运行一个循环,通过应用x值的小增量计算y值将函数转换为x值,然后为Path中的每个计算点添加一个LineTo。以下问题和答案演示了这种方法:




是否有可能将曲线的一个端点连接到另一个节点,所以当该节点的位置改变曲线适应它时?

是的,请尝试下面的示例应用程序,其中曲线末端和控制点绑定到可拖动节点。该曲线适应锚节点位置变化的情况。

  import javafx.application.Application; 
导入javafx.beans.property.DoubleProperty;
import javafx.event.EventHandler;
import javafx.scene。*;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape。*;
import javafx.stage.Stage;

/ **三次曲线如何工作的示例,拖动锚点以改变曲线。 * /
public class CubicCurveManipulator extends Application {
public static void main(String [] args)throws Exception {launch(args); }
@Override public void start(final Stage stage)throws Exception {
CubicCurve curve = createStartingCurve();

Line controlLine1 = new BoundLine(curve.controlX1Property(),curve.controlY1Property(),curve.startXProperty(),curve.startYProperty());
Line controlLine2 = new BoundLine(curve.controlX2Property(),curve.controlY2Property(),curve.endXProperty(),curve.endYProperty());

Anchor start = new Anchor(Color.PALEGREEN,curve.startXProperty(),curve.startYProperty());
Anchor control1 =新的锚点(Color.GOLD,curve.controlX1Property(),curve.controlY1Property());
Anchor control2 =新的锚点(Color.GOLDENROD,curve.controlX2Property(),curve.controlY2Property());
Anchor end = new Anchor(Color.TOMATO,curve.endXProperty(),curve.endYProperty());

stage.setTitle(Cubic Curve Manipulation Sample);
stage.setScene(new Scene(new Group(controlLine1,controlLine2,curve,start,control1,control2,end),400,400,Color.ALICEBLUE));
stage.show();
}

私人CubicCurve createStartingCurve(){
CubicCurve曲线=新CubicCurve();
curve.setStartX(100);
curve.setStartY(100);
curve.setControlX1(150);
curve.setControlY1(50);
curve.setControlX2(250);
curve.setControlY2(150);
curve.setEndX(300);
curve.setEndY(100);
curve.setStroke(Color.FORESTGREEN);
curve.setStrokeWidth(4);
curve.setStrokeLineCap(StrokeLineCap.ROUND);
curve.setFill(Color.CORNSILK.deriveColor(0,1.2,1,0.6));
回报曲线;


class BoundLine extends Line {
BoundLine(DoubleProperty startX,DoubleProperty startY,DoubleProperty endX,DoubleProperty endY){
startXProperty()。bind(startX);
startYProperty()。bind(startY);
endXProperty()。bind(endX);
endYProperty()。bind(endY);
setStrokeWidth(2);
setStroke(Color.GRAY.deriveColor(0,1,1,0.5));
setStrokeLineCap(StrokeLineCap.BUTT);
getStrokeDashArray()。setAll(10.0,5.0);
}
}

//在一个点周围显示一个可拖动的锚点。
class Anchor扩展Circle {
Anchor(Color color,DoubleProperty x,DoubleProperty y){
super(x.get(),y.get(),10);
setFill(color.deriveColor(1,1,1,0.5));
setStroke(color);
setStrokeWidth(2);
setStrokeType(StrokeType.OUTSIDE);

x.bind(centerXProperty());
y.bind(centerYProperty());
enableDrag();
}

//通过用鼠标拖动节点来移动节点。
private void enableDrag(){
final Delta dragDelta = new Delta();
setOnMousePressed(new EventHandler< MouseEvent>(){
@Override public void handle(MouseEvent mouseEvent){
//记录拖放操作的增量距离
dragDelta .x = getCenterX() - mouseEvent.getX();
dragDelta.y = getCenterY() - mouseEvent.getY();
getScene()。setCursor(Cursor.MOVE);
}
});
setOnMouseReleased(new EventHandler< MouseEvent>(){
@Override public void handle(MouseEvent mouseEvent){
getScene()。setCursor(Cursor.HAND);
}
});
setOnMouseDragged(new EventHandler< MouseEvent>(){
@Override public void handle(MouseEvent mouseEvent){
double newX = mouseEvent.getX()+ dragDelta.x;
if (newX> 0& newX< getScene().getWidth()){
setCenterX(newX);
}
double newY = mouseEvent.getY()+ dragDelta。 (newY> 0&& newY< getScene()。getHeight()){
setCenterY(newY);
}
}
});
setOnMouseEntered(new EventHandler< MouseEvent>(){
@Override public void handle(MouseEvent mouseEvent){
if(!mouseEvent.isPrimaryButtonDown()){
getScene() setCursor(Cursor.HAND);
}
}
});
setOnMouseExited(new EventHandler< MouseEvent>(){
@Override public void handle(MouseEvent mouseEvent){
if(!mouseEvent.isPrimaryButtonDown()){
getScene() setCursor(Cursor.DEFAULT);
}
}
});
}

//记录相对的x和y坐标。
私人班级Delta {double x,y; }
}
}

示例程序输出:




I am having a hard time with the CubicCurve in JavaFX. How can one draw for example: y=x^3 ? the mechanism to draw the curve look very unwieldy.

Also is it possible to connect one of the endpoints of the curve to another Node, so when the location of that Node changes the curve adapts to it?

Thanks.

解决方案

I think CubicCurves in JavaFX don't quite work as you think they might. A JavaFX CubicCurve is a Bezier curve which is quite different from the cubic polynomials such y=x^3 you normally encounter in high school mathematics. Everything you never wanted to know about Bezier curves is here.

Bezier curves are often used for generating smooth curves in computer graphics. They are defined by start and end points and a set of control points for manipulating the curve. You can best see how it works by playing with an interactive example where you drag around the start, end and control points to form different curves.

How can one draw for example: y=x^3 ?

While it may be possible to solve the Bezier equations to reduce to a polynomial such as y=x^3, you might want to ask that question on math.stackexchange.com where the caliber of mathematicians is going to be much higher than, for instance, me.

Another way to accomplish this is to run a loop, calculating the y value for small increments of x value by applying the function to the x value, then add a LineTo for each of the calculated points in a Path. The following question and answer demonstrates this approach:

is it possible to connect one of the endpoints of the curve to another Node, so when the location of that Node changes the curve adapts to it?

Yes, try the sample application below where the curve end and control points are bound to draggable nodes. The curve adapts to the changes in the location of the anchor nodes as they are dragged around.

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;

/** Example of how a cubic curve works, drag the anchors around to change the curve. */
public class CubicCurveManipulator extends Application {
  public static void main(String[] args) throws Exception { launch(args); }
  @Override public void start(final Stage stage) throws Exception {
    CubicCurve curve = createStartingCurve();

    Line controlLine1 = new BoundLine(curve.controlX1Property(), curve.controlY1Property(), curve.startXProperty(), curve.startYProperty());
    Line controlLine2 = new BoundLine(curve.controlX2Property(), curve.controlY2Property(), curve.endXProperty(),   curve.endYProperty());

    Anchor start    = new Anchor(Color.PALEGREEN, curve.startXProperty(),    curve.startYProperty());
    Anchor control1 = new Anchor(Color.GOLD,      curve.controlX1Property(), curve.controlY1Property());
    Anchor control2 = new Anchor(Color.GOLDENROD, curve.controlX2Property(), curve.controlY2Property());
    Anchor end      = new Anchor(Color.TOMATO,    curve.endXProperty(),      curve.endYProperty());

    stage.setTitle("Cubic Curve Manipulation Sample");
    stage.setScene(new Scene(new Group(controlLine1, controlLine2, curve, start, control1, control2, end), 400, 400, Color.ALICEBLUE));
    stage.show();
  }

  private CubicCurve createStartingCurve() {
    CubicCurve curve = new CubicCurve();
    curve.setStartX(100);
    curve.setStartY(100);
    curve.setControlX1(150);
    curve.setControlY1(50);
    curve.setControlX2(250);
    curve.setControlY2(150);
    curve.setEndX(300);
    curve.setEndY(100);
    curve.setStroke(Color.FORESTGREEN);
    curve.setStrokeWidth(4);
    curve.setStrokeLineCap(StrokeLineCap.ROUND);
    curve.setFill(Color.CORNSILK.deriveColor(0, 1.2, 1, 0.6));
    return curve;
  }

  class BoundLine extends Line {
    BoundLine(DoubleProperty startX, DoubleProperty startY, DoubleProperty endX, DoubleProperty endY) {
      startXProperty().bind(startX);
      startYProperty().bind(startY);
      endXProperty().bind(endX);
      endYProperty().bind(endY);
      setStrokeWidth(2);
      setStroke(Color.GRAY.deriveColor(0, 1, 1, 0.5));
      setStrokeLineCap(StrokeLineCap.BUTT);
      getStrokeDashArray().setAll(10.0, 5.0);
    }
  }

  // a draggable anchor displayed around a point.
  class Anchor extends Circle { 
    Anchor(Color color, DoubleProperty x, DoubleProperty y) {
      super(x.get(), y.get(), 10);
      setFill(color.deriveColor(1, 1, 1, 0.5));
      setStroke(color);
      setStrokeWidth(2);
      setStrokeType(StrokeType.OUTSIDE);

      x.bind(centerXProperty());
      y.bind(centerYProperty());
      enableDrag();
    }

    // make a node movable by dragging it around with the mouse.
    private void enableDrag() {
      final Delta dragDelta = new Delta();
      setOnMousePressed(new EventHandler<MouseEvent>() {
        @Override public void handle(MouseEvent mouseEvent) {
          // record a delta distance for the drag and drop operation.
          dragDelta.x = getCenterX() - mouseEvent.getX();
          dragDelta.y = getCenterY() - mouseEvent.getY();
          getScene().setCursor(Cursor.MOVE);
        }
      });
      setOnMouseReleased(new EventHandler<MouseEvent>() {
        @Override public void handle(MouseEvent mouseEvent) {
          getScene().setCursor(Cursor.HAND);
        }
      });
      setOnMouseDragged(new EventHandler<MouseEvent>() {
        @Override public void handle(MouseEvent mouseEvent) {
          double newX = mouseEvent.getX() + dragDelta.x;
          if (newX > 0 && newX < getScene().getWidth()) {
            setCenterX(newX);
          }  
          double newY = mouseEvent.getY() + dragDelta.y;
          if (newY > 0 && newY < getScene().getHeight()) {
            setCenterY(newY);
          }  
        }
      });
      setOnMouseEntered(new EventHandler<MouseEvent>() {
        @Override public void handle(MouseEvent mouseEvent) {
          if (!mouseEvent.isPrimaryButtonDown()) {
            getScene().setCursor(Cursor.HAND);
          }
        }
      });
      setOnMouseExited(new EventHandler<MouseEvent>() {
        @Override public void handle(MouseEvent mouseEvent) {
          if (!mouseEvent.isPrimaryButtonDown()) {
            getScene().setCursor(Cursor.DEFAULT);
          }
        }
      });
    }

    // records relative x and y co-ordinates.
    private class Delta { double x, y; }
  }  
}

Sample Program output:

这篇关于CubicCurve JavaFX的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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