如何为多边形设置可拖动边界 - JavaFX
问题描述:
我有一个多边形,可根据需要调整大小,并根据需要在场景周围拖动/移动。但是,我的问题是我怎么能阻止它被拖到按钮或我的树视图列表?这里是我的代码:如何为多边形设置可拖动边界 - JavaFX
public Polygon cfp(ActionEvent event) throws IOException {
Polygon fp = new Polygon();
ObjectProperty<Point2D> mousePosition = new SimpleObjectProperty<>();
//Set the anchor points for the template layout
fp.getPoints().setAll(
350d, 50d,
700d, 50d,
1050d, 50d,
1050d, 350d,
1050d, 650d,
700d, 650d,
350d, 650d,
350d, 350d
);
//Allow the Floor plan to be draggable around the screen
fp.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
mousePosition.set(new Point2D(event.getSceneX(), event.getSceneY()));
}
});
fp.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
double deltaX = event.getSceneX() - mousePosition.get().getX();
double deltaY = event.getSceneY() - mousePosition.get().getY();
fp.setLayoutX(fp.getLayoutX()+deltaX);
fp.setLayoutY(fp.getLayoutY()+deltaY);
mousePosition.set(new Point2D(event.getSceneX(), event.getSceneY()));
}
});
//Set the colour and properties of the template layout
fp.setStroke(Color.DARKRED);
fp.setStrokeWidth(4);
fp.setStrokeLineCap(StrokeLineCap.ROUND);
fp.setFill(Color.MINTCREAM);
container.getChildren().add(fp);
container.getChildren().addAll(createAnchors(fp, fp.getPoints()));
return fp;
}
private ObservableList<Anchor> createAnchors(Polygon polygon, 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 ListWriteDoubleProperty(points, i);
DoubleProperty yProperty = new ListWriteDoubleProperty(points, i + 1);
//Bind the anchors to the polygon, so if its moved so are they
Anchor anchor = new Anchor(Color.BLACK, xProperty, yProperty);
anchor.layoutXProperty().bindBidirectional(polygon.layoutXProperty());
anchor.layoutYProperty().bindBidirectional(polygon.layoutYProperty());
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(anchor);
}
return anchors;
}
//Creating circles to mark the anchor points to help users know where to modify from
class Anchor extends Circle {
private final DoubleProperty x, y;
Anchor(Color color, DoubleProperty x, DoubleProperty y) {
super(x.get(), y.get(), 5);
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 the circle node movable with mouse drag
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 the x and y co-ordinates.
private class Delta {
double x, y;
}
}
这里是我的问题:
而多边形生成有一个锚窗格中的场景,树视图是一个HBox中等等都是,如果这些按钮帮助任何人。
答
发生什么事
您为锚的阻力点检查是基于现场的尺寸,而不是多边形的父容器的尺寸。
如何解决它
更改您的检查,以在父容器的尺寸为基础。
来源:
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);
}
}
});
要:
setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
double newX = mouseEvent.getX() + dragDelta.x;
if (newX > 0 && newX < getParent().getLayoutBounds().getWidth()) {
setCenterX(newX);
}
double newY = mouseEvent.getY() + dragDelta.y;
if (newY > 0 && newY < getParent().getLayoutBounds().getHeight()) {
setCenterY(newY);
}
}
});
确保你的父母是一个可调整大小的父母(如窗格,而不是一组),否则家长不会自动扩展,以填补可以放置多边形的可用区域。
其他问题
如果调整的一幕让在多边形可以呈现的面积比多边形的尺寸,则多边形依然会溢出的可用范围(因为他们有现在收缩小于多边形的大小)。有几种方法可以处理这种情况。
- 你可以放置多边形的一个ScrollPane,因此,如果当前可视区域变得太小,用户可以左右滚动。这可能是首选解决方案,但实施起来会稍微复杂一点(而且这不是你问的问题)。目前我不会提供此示例代码。
-
您可以将剪辑应用于父容器,以便它不会在可见区域外绘制。例如,如果在多边形的容器窗格被命名为polyPane:
Rectangle clip = new Rectangle(); clip.widthProperty().bind(polyPane.widthProperty()); clip.heightProperty().bind(polyPane.heightProperty()); polyPane.setClip(clip);
内容来自StackOverflow的采购需要attribution。
+0
非常感谢您,我遵循您所说的一切,并坚持使用矩形剪辑。非常感激 – TheBeliever12
我还没有编码JavaFX,但不是多边形只限于'窗格'?你能不能把主窗口分成两个“窗格”?一个用于按钮,水平地穿过底部,一个用于多边形区域? – Eric
我不知道为什么,但由于某种原因,我可以将它拖到窗户周围。这些按钮位于HBox中,TreeView也是如此,所以我通常会假定该多边形只能在其父窗格中拖动,但情况并非如此:/ – TheBeliever12
您是否可以在X,Y多边形的极值中进行硬编码?因此限制它的父窗格? – Eric