Reputation: 97
I have a polygon that can be resized as required and dragged/moved around the scene as desired. However, my question is how can I stop it from being dragged over buttons or my treeview list? Here is my code:
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;
}
}
Here is my problem:
the scene where the polygon generates has an Anchor pane, the treeview is in a HBox and so are the buttons if that helps anyone.
Upvotes: 0
Views: 1009
Reputation: 159291
What is Happening
Your check for the drag points for the anchor are based upon the scene dimensions rather than the dimensions of the parent container of the polygon.
How to Fix it
Change your checks to be based upon the parent container dimensions.
From:
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);
}
}
});
To:
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);
}
}
});
Ensure that your parent is a resizable parent (e.g. a Pane and not a Group), otherwise the parent won't automatically expand to fill the available area in which the polygon can be placed.
Additional Concerns
If you resize the scene so that the area in which the polygon can be rendered is smaller than the size of the polygon, then the polygon will still overflow the available bounds (as they have now shrunk smaller than the size of the polygon). There a couple of ways you could handle that situation.
You can apply a clip to the parent container so that it does not draw outside the visible area. For example if your container Pane for the polygon is named polyPane:
Rectangle clip = new Rectangle();
clip.widthProperty().bind(polyPane.widthProperty());
clip.heightProperty().bind(polyPane.heightProperty());
polyPane.setClip(clip);
Content sourced from StackOverflow requires attribution.
Upvotes: 2