I have a chart which I can zoom
final BarChart<String, Number> bc
= new BarChart<String, Number>(xAxis, yAxis);
final double SCALE_DELTA = 1.1;
bc.setOnScroll(new EventHandler<ScrollEvent>()
{
#Override
public void handle(ScrollEvent event)
{
event.consume();
if (event.getDeltaY() == 0)
{
return;
}
double scaleFactor = (event.getDeltaY() > 0) ? SCALE_DELTA : 1 / SCALE_DELTA;
bc.setScaleX(bc.getScaleX() * scaleFactor);
bc.setScaleY(bc.getScaleY() * scaleFactor);
}
});
I can zoom in and zoom out but I cannot drag the chart in order to navigate to specific zoom area. How I can drag the chart by clicking and holding the chart?
P.S I tested this code bit I don't get any result
label.setOnMousePressed(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent mouseEvent)
{
// record a delta distance for the drag and drop operation.
// treePane.x = label.getLayoutX() - mouseEvent.getSceneX();
treePane.setLayoutX(label.getLayoutX() - mouseEvent.getSceneX()); //= label.getLayoutX() - mouseEvent.getSceneX();
//treePane.y = label.getLayoutY() - mouseEvent.getSceneY();
treePane.setLayoutY(label.getLayoutY() - mouseEvent.getSceneY());
label.setCursor(Cursor.MOVE);
}
});
label.setOnMouseReleased(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent mouseEvent)
{
label.setCursor(Cursor.HAND);
}
});
label.setOnMouseDragged(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent mouseEvent)
{
label.setLayoutX(mouseEvent.getSceneX() + treePane.getLayoutX());
label.setLayoutY(mouseEvent.getSceneY() + treePane.getLayoutY());
}
});
label.setOnMouseEntered(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent mouseEvent)
{
label.setCursor(Cursor.HAND);
}
});
Any idea where I'm wrong?
You Can Use this code for drag and drog label This is solution for javafx
#FXML
public void lblDragMouseDragged(MouseEvent m)
{
System.out.println("Mouse Dragged");
System.out.println(lblDragTest.getLayoutX());
System.out.println(lblDragTest.getLayoutY());
int diffX;
int diffY;
int x = (int) (m.getX()+lblDragTest.getLayoutX()-rootAnchorPane.getLayoutX());
int y = (int) (m.getY()+lblDragTest.getLayoutY()-rootAnchorPane.getLayoutY());
if (y > 0 && x > 0 && y < rootAnchorPane.getHeight() && x < rootAnchorPane.getWidth())
{
lblDragTest.setLayoutX(x);
lblDragTest.setLayoutY(y);
}
}
Related
This question already has an answer here:
How to change a shape property using its border in JavaFX?
(1 answer)
Closed 5 years ago.
I am try to allow users to drag/resize a rectangle in javafx.
Rectangle in javafx uses TopLeft-X, Y, height and width to draw.
What I am trying to do is to have 4 handles at each corner of the rectangle to allow users to drag the handle. Which will result in resizing the rectangle.
My application throws a stackoverflow exception which I know is caused by the recursive call of the listener.
Did i forget something? Or is there some listener that is unnecessary?
public class Handler extends Circle
{
private double deltaX;
private double deltaY;
private static final double DEFAULT_RADIUS = 10;
private static final Color DEFAULT_COLOR = Color.GOLD;
private DoubleProperty xProperty;
private DoubleProperty yProperty;
public Handler(DoubleProperty xProperty, DoubleProperty yProperty)
{
super(DEFAULT_RADIUS, DEFAULT_COLOR);
this.xProperty = xProperty;
this.yProperty = yProperty;
init();
}
private void init()
{
setFill(DEFAULT_COLOR.deriveColor(1, 1, 1, 0.5));
setStroke(DEFAULT_COLOR);
setStrokeWidth(2);
setStrokeType(StrokeType.OUTSIDE);
centerXProperty().bind(xProperty);
centerYProperty().bind(yProperty);
setOnMousePressed(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent mouseEvent)
{
mouseEvent.consume();
deltaX = getCenterX() - mouseEvent.getX();
deltaY = getCenterY() - mouseEvent.getY();
getScene().setCursor(javafx.scene.Cursor.MOVE);
}
});
setOnMouseReleased(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent mouseEvent)
{
getScene().setCursor(javafx.scene.Cursor.HAND);
}
});
setOnMouseEntered(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent mouseEvent)
{
if (!mouseEvent.isPrimaryButtonDown())
{
getScene().setCursor(javafx.scene.Cursor.HAND);
}
}
});
setOnMouseExited(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent mouseEvent)
{
if (!mouseEvent.isPrimaryButtonDown())
{
getScene().setCursor(javafx.scene.Cursor.DEFAULT);
}
}
});
setOnMouseDragged(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent mouseEvent)
{
double newX = mouseEvent.getX() + deltaX;
double newY = mouseEvent.getY() + deltaY;
if (newX > 0 && newX < getScene().getWidth())
{
xProperty.set(newX);
}
if (newY > 0 && newY < getScene().getHeight())
{
yProperty.set(newY);
}
}
});
}
//JavaFx Accessor and mutator
}
public class CustomRectangle extends Rectangle
{
private DoubleProperty topRightX;
private DoubleProperty topRightY;
private DoubleProperty btmLeftX;
private DoubleProperty btmLeftY;
private DoubleProperty btmRightX;
private DoubleProperty btmRightY;
private DoubleProperty customeWidth;
private DoubleProperty customHeight;
public CustomRectangle()
{
super();
init();
}
public CustomRectangle(double x, double y, double width, double height)
{
super(x, y, width, height);
init();
}
public CustomRectangle(double width, double height, Paint fill)
{
super(width, height, fill);
init();
}
public CustomRectangle(double width, double height)
{
super(width, height);
init();
}
private void init()
{
topRightX = new SimpleDoubleProperty();
topRightY = new SimpleDoubleProperty();
btmLeftX = new SimpleDoubleProperty();
btmLeftY = new SimpleDoubleProperty();
btmRightX = new SimpleDoubleProperty();
btmRightY = new SimpleDoubleProperty();
topRightX.addListener((observable, oldValue, newValue) ->
{
this.setWidth(this.getWidth() + (newValue.doubleValue() - oldValue.doubleValue()));
});
topRightY.addListener((observable, oldValue, newValue) ->
{
this.setY(newValue.doubleValue());
this.setHeight(this.getHeight() - (newValue.doubleValue() - oldValue.doubleValue()));
});
btmLeftX.addListener((observable, oldValue, newValue) ->
{
this.setX(newValue.doubleValue());
this.setWidth(this.getWidth() - (newValue.doubleValue() - oldValue.doubleValue()));
});
btmLeftY.addListener((observable, oldValue, newValue) ->
{
this.setY(newValue.doubleValue());
this.setHeight(this.getHeight() + (newValue.doubleValue() - oldValue.doubleValue()));
});
btmRightX.addListener((observable, oldValue, newValue) ->
{
this.setWidth(this.getWidth() + (newValue.doubleValue() - oldValue.doubleValue()));
});
btmRightY.addListener((observable, oldValue, newValue) ->
{
this.setHeight(this.getHeight() + (newValue.doubleValue() - oldValue.doubleValue()));
});
this.xProperty().addListener((observable, oldValue, newValue) ->
{
btmLeftX.set(newValue.doubleValue());
topRightX.set(newValue.doubleValue() + this.getWidth());
btmRightX.set(newValue.doubleValue() + this.getWidth());
});
this.yProperty().addListener((observable, oldValue, newValue) ->
{
btmLeftY.set(newValue.doubleValue() + this.getHeight());
topRightY.set(newValue.doubleValue());
btmRightY.set(newValue.doubleValue() + this.getHeight());
});
this.widthProperty().addListener((observable, oldValue, newValue) ->
{
topRightX.set(this.getX() + (newValue.doubleValue() - oldValue.doubleValue()));
btmRightX.set(this.getX() + (newValue.doubleValue() - oldValue.doubleValue()));
});
this.heightProperty().addListener((observable, oldValue, newValue) ->
{
btmLeftY.set(this.getY() + (newValue.doubleValue() - oldValue.doubleValue()));
btmRightY.set(this.getY() + (newValue.doubleValue() - oldValue.doubleValue()));
});
}
//JavaFx Accessor and Mutator
}
public class FeatureHelper
{
private static double orgSceneX;
private static double orgSceneY;
private static double orgTranslateX;
private static double orgTranslateY;
public static CustomRectangle createDraggableRectangle(double x, double y, double width, double height,
boolean resizeImage)
{
CustomRectangle rect = new CustomRectangle(x, y, width, height);
// top left resize handle:
Handler topLeftHandle = new Handler(rect.topLeftXProperty(), rect.topLeftYProperty());
// top right resize handle:
Handler topRightHandle = new Handler(rect.topRightXProperty(), rect.topRightYProperty());
// bottom left resize handle:
Handler btmLeftHandle = new Handler(rect.btmLeftXProperty(), rect.btmLeftYProperty());
// bottom right resize handle:
Handler btmRightHandle = new Handler(rect.btmRightXProperty(), rect.btmRightYProperty());
// force circles to live in same parent as rectangle:
rect.parentProperty().addListener((obs, oldParent, newParent) ->
{
for (Circle c : Arrays.asList(topLeftHandle, topRightHandle, btmLeftHandle, btmRightHandle))
{
if (newParent != null)
{
((Pane) newParent).getChildren().add(c);
}
}
});
rect.setOnMousePressed(event ->
{
event.consume();
orgSceneX = event.getSceneX();
orgSceneY = event.getSceneY();
Node p = ((Node) (event.getSource()));
orgTranslateX = p.getTranslateX();
orgTranslateY = p.getTranslateY();
});
rect.setOnMouseDragged(event ->
{
double offsetX = event.getSceneX() - orgSceneX;
double offsetY = event.getSceneY() - orgSceneY;
double newTranslateX = orgTranslateX + offsetX;
double newTranslateY = orgTranslateY + offsetY;
Node p = ((Node) (event.getSource()));
p.setTranslateX(newTranslateX);
p.setTranslateY(newTranslateY);
for(Circle circle : Arrays.asList(topLeftHandle, topRightHandle, btmLeftHandle, btmRightHandle))
{
circle.setTranslateX(newTranslateX);
circle.setTranslateY(newTranslateY);
}
});
return rect;
}
}
You should have a look at this nice Example from karakullukcuhuseyin -->
https://github.com/karakullukcuhuseyin/JavaFX-ImageCropper
He extended the Rectangle Class as well and is using his custom Rectangle to select an area in an Image.
Scenario : I have two panel one of them has slider and another has drag gable pane .
Case I : if Pane(i.e Drag gable ) moved in forward or backward direction .node on slider moved with respective dimension in same direction of pane moved.
Case II : this functionality works vice versa .
(Drag gable pane with slider)
(slider with drag gable Pane).
so how i can achieve it..
Thank You!
You create a property for the horizontal direction. Then you change the property whenever the slider or the pane moves. Depending on the property changes you move the pane.
public class Main extends Application {
DoubleProperty xProperty = new SimpleDoubleProperty();
double min = 0;
double max = 100;
#Override
public void start(Stage primaryStage) {
try {
Pane root = new Pane();
// rectangle
Pane pane = new Pane();
pane.setStyle("-fx-background-color:blue");
pane.setPrefSize(50, 50);
pane.relocate(min, 50);
// make rectangle movable
MouseGestures mg = new MouseGestures();
mg.makeDraggable(pane);
// slider
Slider slider = new Slider(min, max, min);
slider.valueProperty().bindBidirectional( xProperty);
root.getChildren().addAll(slider, pane);
// move horizontally, clamp horizontal movement
xProperty.addListener(new ChangeListener<Number>() {
#Override
public void changed( ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
// clamp x
double x = newValue.doubleValue();
if( x < min) {
x = min;
}
if( x > max) {
x = max;
}
pane.relocate( x, pane.getBoundsInParent().getMinY());
}
});
Scene scene = new Scene(root,1024,768);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
public class MouseGestures {
final DragContext dragContext = new DragContext();
public void makeDraggable(final Node node) {
node.setOnMousePressed(onMousePressedEventHandler);
node.setOnMouseDragged(onMouseDraggedEventHandler);
}
EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
Node node = (Node) event.getSource();
dragContext.x = node.getBoundsInParent().getMinX() - event.getScreenX();
}
};
EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
double offsetX = event.getScreenX() + dragContext.x;
xProperty.set(offsetX);
}
};
class DragContext {
double x;
}
}
}
I want to select few images available on my Canvas. How to select multiple of them using control key?
You create a model, e. g.
List<Node> selectionModel = new ArrayList<Node>();
and add a listener to each node, e. g.
imageView.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
if( event.isControlDown()) {
selectionModel.add( (Node) event.getSource());
// logging
System.out.println("Items in model:");
selectionModel.forEach(n -> System.out.println(n));
}
});
Of course you need to provide an option to clear the selection model, e. g. by clicking outside on the scene instead of an ImageView.
Here's a more sophisticated example. Supports rubberband selection, ctrl for selection toggle, shift for adding to selection and click on background to clear the selection.
public class ImageSelection extends Application {
Image image = new Image("http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/320px-Siberischer_tiger_de_edit02.jpg");
SelectionModel selectionModel = new SelectionModel();
#Override
public void start(Stage primaryStage) {
Pane pane = new Pane();
double width = image.getWidth();
double height = image.getHeight();
double padding = 20;
for( int row=0; row < 4; row++) {
for( int col=0; col < 4; col++) {
ImageView imageView = new ImageView( image);
imageView.relocate( padding * (col+1) + width * col, padding * (row + 1) + height * row);
pane.getChildren().add(imageView);
}
}
Scene scene = new Scene( pane, 1800, 1200);
primaryStage.setScene( scene);
primaryStage.show();
new RubberBandSelection( pane);
}
public static void main(String[] args) {
launch(args);
}
private class SelectionModel {
Set<Node> selection = new HashSet<>();
public void add( Node node) {
node.setStyle("-fx-effect: dropshadow(three-pass-box, red, 10, 10, 0, 0);");
selection.add( node);
}
public void remove( Node node) {
node.setStyle("-fx-effect: null");
selection.remove( node);
}
public void clear() {
while( !selection.isEmpty()) {
remove( selection.iterator().next());
}
}
public boolean contains( Node node) {
return selection.contains(node);
}
public void log() {
System.out.println( "Items in model: " + Arrays.asList( selection.toArray()));
}
}
private class RubberBandSelection {
final DragContext dragContext = new DragContext();
Rectangle rect;
Pane group;
public RubberBandSelection( Pane group) {
this.group = group;
rect = new Rectangle( 0,0,0,0);
rect.setStroke(Color.BLUE);
rect.setStrokeWidth(1);
rect.setStrokeLineCap(StrokeLineCap.ROUND);
rect.setFill(Color.LIGHTBLUE.deriveColor(0, 1.2, 1, 0.6));
group.addEventHandler(MouseEvent.MOUSE_PRESSED, onMousePressedEventHandler);
group.addEventHandler(MouseEvent.MOUSE_DRAGGED, onMouseDraggedEventHandler);
group.addEventHandler(MouseEvent.MOUSE_RELEASED, onMouseReleasedEventHandler);
}
EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
dragContext.mouseAnchorX = event.getSceneX();
dragContext.mouseAnchorY = event.getSceneY();
rect.setX(dragContext.mouseAnchorX);
rect.setY(dragContext.mouseAnchorY);
rect.setWidth(0);
rect.setHeight(0);
group.getChildren().add( rect);
event.consume();
}
};
EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if( !event.isShiftDown() && !event.isControlDown()) {
selectionModel.clear();
}
for( Node node: group.getChildren()) {
if( node instanceof ImageView) {
if( node.getBoundsInParent().intersects( rect.getBoundsInParent())) {
if( event.isShiftDown()) {
selectionModel.add( node);
} else if( event.isControlDown()) {
if( selectionModel.contains( node)) {
selectionModel.remove( node);
} else {
selectionModel.add( node);
}
} else {
selectionModel.add( node);
}
}
}
}
selectionModel.log();
rect.setX(0);
rect.setY(0);
rect.setWidth(0);
rect.setHeight(0);
group.getChildren().remove( rect);
event.consume();
}
};
EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
double offsetX = event.getSceneX() - dragContext.mouseAnchorX;
double offsetY = event.getSceneY() - dragContext.mouseAnchorY;
if( offsetX > 0)
rect.setWidth( offsetX);
else {
rect.setX(event.getSceneX());
rect.setWidth(dragContext.mouseAnchorX - rect.getX());
}
if( offsetY > 0) {
rect.setHeight( offsetY);
} else {
rect.setY(event.getSceneY());
rect.setHeight(dragContext.mouseAnchorY - rect.getY());
}
event.consume();
}
};
private final class DragContext {
public double mouseAnchorX;
public double mouseAnchorY;
}
}
}
I want to create Pie chart with caption. When I move the mouse over the Pie chart the text is displayed very smoothly.
public void naiveAddData(String name, double value)
{
pieChartData.add(new Data(name, value));
caption = new Label();
caption.setTextFill(Color.DARKORANGE);
caption.setStyle("-fx-font: 24 arial;");
for (final Data data : chart.getData())
{
data.getNode().addEventHandler(MouseEvent.MOUSE_MOVED,
new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent e)
{
caption.setTranslateX(e.getSceneX() + 15);
caption.setTranslateY(e.getSceneY());
caption.setText(String.valueOf(data.getPieValue()) + "%");
}
});
}
}
But when I move the mouse outside the Pie Chart the caption is still there. It's not removed. How I can fix this?
P.S I managed to solve the problem this way:
data.getNode().addEventHandler(MouseEvent.MOUSE_MOVED,
new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent e)
{
caption.setTranslateX(e.getSceneX() + 15);
caption.setTranslateY(e.getSceneY());
caption.setText(String.valueOf(data.getPieValue()) + "%");
caption.setVisible(true);
}
});
data.getNode().addEventHandler(MouseEvent.MOUSE_EXITED,
new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent e)
{
caption.setVisible(false);
}
});
}
Is there any better solution?
If you have the parent of the caption you can remove it from its parent on mouse exit and add it again on mouse enter.
Parent captionparent = ...
...
data.getNode().addEventHandler(MouseEvent.MOUSE_EXITED,
new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent e)
{
captionparent.getChildren().remove(caption);
}
});
Here is a complete example using a Tooltip.
public class ChartingMain extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
PieChart pc = new PieChart();
pc.setTitle("Most popular programming languages");
ObservableList<PieChart.Data> pcdata = FXCollections.<PieChart.Data>observableArrayList();
pcdata.add(new PieChart.Data("C#", 20d));
pcdata.add(new PieChart.Data("Java",800d));
pcdata.add(new PieChart.Data("C/C++", 400d));
final double total = 20d + 800d + 400d;
pc.dataProperty().set(pcdata);
stage.setScene(new Scene(pc));
stage.show();
for(PieChart.Data data : pc.getData()){
final Tooltip t = new Tooltip(data.getName() + " : " + new DecimalFormat("#.##").format((data.getPieValue() / total) * 100) + " %");
data.getNode().setOnMouseEntered(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent me) {
if(me.getSource() instanceof Node){
Node sender = (Node) me.getSource();
Tooltip.install(sender, t);
sender.setEffect(new Glow(0.5));
}
}});
data.getNode().setOnMouseExited(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent me) {
if(me.getSource() instanceof Node){
Node sender = (Node) me.getSource();
sender.setEffect(null);
t.hide();
}
}});
}
}
}
Is there a way to modify a polygon in JavaFX? For example if I have a triangle and I press and then drag a point from that triangle, the triangle will modify with the new coordinates of the point.
Layer some control nodes over the corners of the polygon.
Attach appropriate event handlers to the control nodes so that they can be dragged around.
Modify the polygon's points as the control node is moved (using change listeners attached to each of the control node's location properties).
Here is a sample solution:
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; }
}
}
I derived this solution from: CubicCurve JavaFX