3

JavaFXでポリゴンを変更する方法はありますか? たとえば、三角形があり、その三角形からポイントを押してドラッグすると、三角形はポイントの新しい座標で変更されます。

4

1 に答える 1

7
  1. ポリゴンの角にいくつかのコントロール ノードを重ねます。
  2. 適切なイベント ハンドラーをコントロール ノードにアタッチして、ドラッグできるようにします。
  3. コントロール ノードの移動に合わせてポリゴンのポイントを変更します (各コントロール ノードの位置プロパティにアタッチされた変更リスナーを使用)。

サンプル ソリューションは次のとおりです。

import javafx.scene.Scene;

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.beans.value.*;
import javafx.collections.*;
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;

/** Drag the anchors around to change a polygon's points. */
public class TriangleManipulator extends Application {
  public static void main(String[] args) throws Exception { launch(args); }

  // main application layout logic.
  @Override public void start(final Stage stage) throws Exception {
    Polygon triangle = createStartingTriangle();

    Group root = new Group();
    root.getChildren().add(triangle);
    root.getChildren().addAll(createControlAnchorsFor(triangle.getPoints()));

    stage.setTitle("Triangle Manipulation Sample");
    stage.setScene(
        new Scene(
            root,
            400, 400, Color.ALICEBLUE
        )
    );
    stage.show();
  }

  // creates a triangle.
  private Polygon createStartingTriangle() {
    Polygon triangle = new Polygon();

    triangle.getPoints().setAll(
        100d, 100d,
        150d, 50d,
        250d, 150d
    );

    triangle.setStroke(Color.FORESTGREEN);
    triangle.setStrokeWidth(4);
    triangle.setStrokeLineCap(StrokeLineCap.ROUND);
    triangle.setFill(Color.CORNSILK.deriveColor(0, 1.2, 1, 0.6));

    return triangle;
  }

  // @return a list of anchors which can be dragged around to modify points in the format [x1, y1, x2, y2...]
  private ObservableList<Anchor> createControlAnchorsFor(final ObservableList<Double> points) {
    ObservableList<Anchor> anchors = FXCollections.observableArrayList();

    for (int i = 0; i < points.size(); i+=2) {
      final int idx = i;

      DoubleProperty xProperty = new SimpleDoubleProperty(points.get(i));
      DoubleProperty yProperty = new SimpleDoubleProperty(points.get(i + 1));

      xProperty.addListener(new ChangeListener<Number>() {
        @Override public void changed(ObservableValue<? extends Number> ov, Number oldX, Number x) {
          points.set(idx, (double) x);
        }
      });

      yProperty.addListener(new ChangeListener<Number>() {
        @Override public void changed(ObservableValue<? extends Number> ov, Number oldY, Number y) {
          points.set(idx + 1, (double) y);
        }
      });

      anchors.add(new Anchor(Color.GOLD, xProperty, yProperty));
    }

    return anchors;
  }

  // a draggable anchor displayed around a point.
  class Anchor extends Circle {
    private final DoubleProperty x, y;

    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);

      this.x = x;
      this.y = y;

      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; }
  }
}

三角

私はこのソリューションを以下から派生させました: CubicCurve JavaFX

于 2013-04-12T22:49:34.437 に答える