我需要为大学里的项目创建一个类似隧道的生成曲线。我在Internet上找到了一些代码,允许我拖动曲线的控制点(附加到Anchor对象)。
但是,我想通过按箭头键(“向上”和“向下”)更改控制点Ylocation是可能的,并且它根本不起作用。我一直试图无望地解决这个问题,但我找不到出路。
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
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 testsdfasdf extends Application {
public static void main(String[] args) throws Exception { launch(args); }
@Override public void start(Stage primaryStage) throws Exception {
QuadCurve curve = createStartingCurve();
final BorderPane root = new BorderPane();
Scene scene = new Scene(root, 1000, 1000);
final Anchor control2 = new Anchor(Color.GOLDENROD, curve.controlXProperty(), curve.controlYProperty());
root.getChildren().add(curve);
root.getChildren().add(control2);
primaryStage.setTitle("Quadcurve Manipulation");
primaryStage.setScene(scene);
primaryStage.show();
}
private QuadCurve createStartingCurve() {
QuadCurve curve = new QuadCurve();
curve.setStartX(100);
curve.setStartY(100);
curve.setControlX(200);
curve.setControlY(50);
curve.setEndX(300);
curve.setEndY(100);
curve.setStroke(Color.BLACK);
curve.setStrokeWidth(10);
curve.setStrokeLineCap(StrokeLineCap.ROUND);
curve.setFill(Color.CORNSILK.deriveColor(0, 1.2, 1, 0.6));
return curve;
}
// 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));
y.bind(centerYProperty());
enableDrag();
changeCurve();
}
private void changeCurve() {
setOnKeyPressed((event) -> {
System.out.println(event.getCode() == KeyCode.DOWN);
if (event.getCode() == KeyCode.DOWN) {
double newY = getCenterY();
while (newY > 0 && newY < getScene().getHeight()) {
setCenterY(newY);
newY+=1;
}
}
else if (event.getCode() == KeyCode.UP) {
double newY = getCenterY();
while (newY > 0 && newY < getScene().getHeight()) {
setCenterY(newY);
newY-=1;
}
}
});
setOnKeyReleased((event) -> {
if (event.getCode() == KeyCode.DOWN) {
}
if (event.getCode() == KeyCode.UP) {
}
});
}
// make a node movable by dragging it around with the mouse.
private void enableDrag() {
setOnMousePressed(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
// record a delta distance for the drag and drop operation.
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 newY = mouseEvent.getY();
System.out.println(newY);
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);
}
}
});
}
}
}
也许这里的代码太多了。但这就是实际绘制曲线并使用 enableDrag()函数使其可拖动。
changeCurve()功能不起作用,这就是问题所在。
答案 0 :(得分:5)
<强>问题强>
除非重点关注,否则节点不会侦听事件。你的圈子永远不会得到关注,因此永远不会对关键事件做出反应。
<强>解决方案强>
其中一个 easy 解决方案是在显示舞台后请求焦点。
primaryStage.show();
control2.requestFocus();
另一种解决方案是将场景onKeyPressedProperty
绑定到圈子onKeyPressedProperty
。这将把场景中发生的所有按键事件绑定到圆圈。
在某些情况下,您可能不希望这样做..
scene.onKeyPressedProperty().bind(control2.onKeyPressedProperty());
您的handle()
也存在一个小问题。不需要while loop
。你只想setCenterY()
得到一个小于/大于前一个值的值,具体取决于按下的键。
setOnKeyPressed((event) -> {
if (event.getCode() == KeyCode.DOWN && getCenterY() < getScene().getHeight()){
setCenterY(getCenterY() + 5);
} else if (event.getCode() == KeyCode.UP && getCenterY() > 0) {
setCenterY(getCenterY() - 5);
}
});