Drawing a rectangle in all directions with javaFX fails - javafx

I use this code to draw a rectangle while dragging the mouse. The problem is that i only can draw from left down to the right.
Here is my code:
public class functionalTest extends Application {
BorderPane pane;
Rectangle rect;
Group group;
SimpleDoubleProperty rectinitX = new SimpleDoubleProperty();
SimpleDoubleProperty rectinitY = new SimpleDoubleProperty();
SimpleDoubleProperty rectX = new SimpleDoubleProperty();
SimpleDoubleProperty rectY = new SimpleDoubleProperty();
#Override
public void start(Stage stage) {
pane = new BorderPane();
Scene scene = new Scene(pane, 800, 600);
stage.setScene(scene);
group = new Group();
Circle circle = new Circle(200, 200, 25);
circle.setFill(Color.HOTPINK);
group.getChildren().add(circle);
scene.setOnMouseDragged(mouseHandler);
scene.setOnMousePressed(mouseHandler);
scene.setOnMouseReleased(mouseHandler);
rect = getNewRectangle();
rect.widthProperty().bind(rectX.subtract(rectinitX));
rect.heightProperty().bind(rectY.subtract(rectinitY));
pane.getChildren().add(rect);
pane.getChildren().add(group);
stage.show();
ArrayList<Node> containedNodesArray = new ArrayList<Node>();
containedNodesArray = Main.dragBoxSelection(group, rect);
if (containedNodesArray.size() > 0) {
System.out.println("Success");
}
}
EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getEventType() == MouseEvent.MOUSE_PRESSED) {
rect.setX(mouseEvent.getX());
rect.setY(mouseEvent.getY());
rectinitX.set(mouseEvent.getX());
rectinitY.set(mouseEvent.getY());
} else if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED) {
rectX.set(mouseEvent.getX());
rectY.set(mouseEvent.getY());
System.out.println("RECTX"+rectX.getValue());
System.out.println("RECTY"+rectY.getValue());
ArrayList<Node> containedNodesArray = new ArrayList<Node>();
containedNodesArray = Main.dragBoxSelection(group, rect);
if (containedNodesArray.size() > 0) {
System.out.println("Success");
}
} else if (mouseEvent.getEventType() == MouseEvent.MOUSE_RELEASED) {
// Clone the rectangle
Rectangle r = getNewRectangle();
r.setX(rect.getX());
r.setY(rect.getY());
r.setWidth(rect.getWidth());
r.setHeight(rect.getHeight());
pane.getChildren().add(r);
// Hide the rectangle
rectX.set(0);
rectY.set(0);
}
}
};
private Rectangle getNewRectangle() {
Rectangle r = new Rectangle();
r.setFill(Color.web("blue", 0.1));
r.setStroke(Color.BLUE);
return r;
}
public static void main(String[] args) {
launch(args);
}
}
Please can anyone help me draw in other direcions from right up to left, left up to the right and right down to he left.

Don't know if it worked for anyone but no luck for me. However, this does work for me in JavaFX 8:
if( event.getEventType() == MouseDragEvent.MOUSE_DRRAGGED ) {
double deltaX = event.getX() - initialPt.getX();
double deltaY = event.getY() - initialPt.getY();
if( deltaX < 0 ) {
rect.setX( event.getX() );
rect.setWidth( -deltaX );
}
else {
rect.setX( initialPt.getX() );
rect.setWidth( event.getX() - initialPt.getX() );
}
if( deltaY < 0 ) {
rect.setY( event.getY() );
rect.setHeight( -deltaY );
}
else {
rect.setY( initialPt.getY() );
rect.setHeight( event.getY() - initialPt.getY() );
}
}
No need to call setTranslateX() or setTranslateY(). Don't know if that could be related to which FX version you're using.

This is what you need to do:
When the mouse is dragged: get the dx = mouseEvent.getX() - initial X; if dx < 0 then you need to setTranslateX(dx) and setWidth(-dx)
else setTranslateX(0) and setWidth(dx)
Do the same for the Y coordinate, however this time use height not width;
This is all.

I replaced the code to be like this:
EventHandler mouseHandler = new EventHandler() {
#Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getEventType() == MouseEvent.MOUSE_PRESSED) {
rectinitX.set(mouseEvent.getX());
rectinitY.set(mouseEvent.getY());
} else if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED) {
Double width = mouseEvent.getX() - rectinitX.getValue();
if (width < 0) {
rectX.set(mouseEvent.getX());
rect.setTranslateX(width);
rect.widthProperty().bind(rectinitX.subtract(rectX));
System.out.println(rect.getWidth());
} else {
rectX.set(mouseEvent.getX());
rect.setTranslateX(0);
rect.widthProperty().bind(rectX.subtract(rectinitX));
}
} else if (mouseEvent.getEventType() == MouseEvent.MOUSE_RELEASED) {
// Clone the rectangle
Rectangle r = getNewRectangle();
r.setX(rect.getX());
r.setY(rect.getY());
r.setWidth(rect.getWidth());
r.setHeight(rect.getHeight());
pane.getChildren().add(r);
}
}
};
I only wanted to try your solution for the width vaues at first but it doesn't seem to work. Do you have any comments on my implementation?

You are missing the height parameters.
if (event.getEventType() == MouseEvent.MOUSE_PRESSED) {
rect.setX(event.getX());
rect.setY(event.getY());
rectinitX.set(event.getX());
rectinitY.set(event.getY());
} else if (event.getEventType() == MouseEvent.MOUSE_DRAGGED) {
Double dx = event.getX() - rectinitX.getValue();
Double dy = event.getY() - rectinitY.getValue();
if (dx < 0) {
rectX.set(event.getX());
rect.setTranslateX(dx);
rect.widthProperty().bind(rectinitX.subtract(rectX));
} else {
rectX.set(event.getX());
rect.setTranslateX(0);
rect.widthProperty().bind(rectX.subtract(rectinitX));
}
if(dy < 0) {
rectY.set(event.getY());
rect.setTranslateY(dy);
rect.heightProperty().bind(rectinitX.subtract(rectX));
} else {
rectY.set(event.getY());
rect.setTranslateY(0);
rect.heightProperty().bind(rectY.subtract(rectinitY));
}
} else if (event.getEventType() == MouseEvent.MOUSE_RELEASED) {
// Clone the rectangle
Rectangle r = getNewRectangle();
r.setX(rect.getX());
r.setY(rect.getY());
r.setWidth(rect.getWidth());
r.setHeight(rect.getHeight());
pane.getChildren().add(r);
// Hide the rectangle
rectX.set(0);
rectY.set(0);
}}}};
This is the exact code for drawing in different directions except doesn´t work unfortunately from left bottom to right top and I cannot figure it out.
Works perfectly in default aka left to right but there is a code bug when drawing right to left.
If someone could figure it out, I´ll be much appricated

it should read
if(dy < 0)
{
rectY.set(mouseEvent.getY());
rect.setTranslateY(dy);
rect.heightProperty().bind(rectinitY.subtract(rectY));
}

Related

How to use Javafx and scenebuilder to draw on canvas (Group element)

i am new to scenebuilder and fx and need some help.
I have the class Puffer , TestMain and MainViewController.
I tried to paint on the canvas and it worked.I tried Puffer and it worked too.
Now I wanted to use scenebuilder and have my problems.I would like to draw the Group from Puffer on the canvas with a button and don't know what's the best solution.I already tried to modify Puffer without any result.
public class Puffer {
Group root = new Group();
public void draw() {
for (int x = 0; x < 800; x++) {
for (int y = 0; y < 600; y++) {
Complex z0 = new Complex(0.11, 0.123); //!!!!!!!!!!!!! under 1
Complex c = new Complex(x / 400.0 - 2, 1 - y / 400.0);
if (isBounded(iterate(z0, c))) {
drawPoint(x, y, root);
}
}
}
// primaryStage.setScene(new Scene(root, 800, 600));
// primaryStage.show();
}
public void drawPoint(int x, int y, Group root) {
int max = 255;
int min = 0;
int range = max - min + 1;
Line line = new Line(x, y, x, y);
// line.setStroke(Color.rgb((int)(Math.random() * range) + min,(int)(Math.random() * range) + min,(int)(Math.random() * range) + min));
root.getChildren().add(line);
}
public Complex iterate(Complex z0, Complex c) {
Complex zn = z0;
for (int i = 0; i < 20; i++) {
zn.square().add(c);
}
return zn;
}
public boolean isBounded(Complex zn) {
return zn.module() < 2;
}
public class MainViewController {
#FXML
Canvas canvas;
// Event Listener on Button.onAction
#FXML
public void btnOkClicked(ActionEvent event) {
System.out.println("Test");
}
#FXML
public void drawCanvas(){
// GraphicsContext gc = canvas.getGraphicsContext2D();
// gc.setLineWidth(3);
// gc.setStroke(Color.BLACK);
// System.out.println("drawCanvas");
//
// try {
// canvas.setOnMousePressed(event -> {
// System.out.println("Mouse click");
// gc.beginPath();
// gc.lineTo(event.getSceneX(), event.getSceneY());
// gc.stroke();
// });
//
// canvas.setOnMouseDragged(event -> {
// System.out.println("Mouse dragged");
// gc.lineTo(event.getSceneX(), event.getSceneY());
// gc.stroke();
// });
// }catch (Exception e){
// System.out.println(e);
// System.exit(0);
// }
}
public class TestMain extends Application {
#Override
public void start(Stage s1) throws Exception {
try {
Parent root = FXMLLoader.load(getClass().getResource("MainView.fxml"));
Scene scene = new Scene(root);
s1.setTitle("Test");
s1.setScene(scene);
s1.show();
}catch(Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}

Relocation of an image after a detection of a collision

I have figured out how to detect the collision of the rectangle and the image but where I am having problems is when I call the method to relocate the image it does it like 10 times in a row then won't work again.
I am making my first game in JavaFX. Im trying to make a basic snake game but haven't been able to figure out what is wrong with relocating the food after the snake collides with it.
public class Main extends Application {
Stage window;
Scene mainScene;
private final int WIDTH = 500;
private final int HEIGHT = 500;
Timeline timeline;
private Direction action = Direction.RIGHT;
private Rectangle snakeHead;
private final int speed = 3;
private int xSpeed = 3;
private int ySpeed = 3;
private int snakeW = 20;
private int snakeH = 20;
private BoundingBox snakeBox;
private BoundingBox foodBox;
private ImageView food;
private Random rand = new Random();
private double foodX;
private double foodY;
enum Direction {
LEFT,RIGHT,UP,DOWN;
}
private Parent createContent(){
Pane root = new Pane();
//food = new Food();
food = new ImageView(new Image("resources/apple.png"));
food.setFitHeight(25);
food.setFitWidth(25);
food.setPreserveRatio(true);
newFood();
foodBox = new BoundingBox(foodX,foodY,20,20);
snakeHead = new Rectangle(snakeW,snakeH);
snakeHead.setTranslateX(200);
snakeHead.setTranslateY(200);
snakeBox = new BoundingBox(snakeHead.getTranslateX(),snakeHead.getTranslateY(),snakeW,snakeH);
timeline = new Timeline(new KeyFrame(Duration.millis(16), e-> {
//Snake movement
if(action == Direction.LEFT) {snakeHead.setTranslateX(snakeHead.getTranslateX() - xSpeed);}
if(action == Direction.RIGHT) {snakeHead.setTranslateX(snakeHead.getTranslateX() + xSpeed);}
if(action == Direction.UP) {snakeHead.setTranslateY(snakeHead.getTranslateY() - ySpeed);}
if(action == Direction.DOWN) {snakeHead.setTranslateY(snakeHead.getTranslateY() + ySpeed);}
//Stops snake at edges of screen
if(snakeHead.getTranslateX() <= 0){
xSpeed = 0;
if(action == Direction.RIGHT){xSpeed = speed;}
}
if(snakeHead.getTranslateX() >= WIDTH - snakeW){
xSpeed = 0;
if(action == Direction.LEFT){xSpeed = speed;}
}
if(snakeHead.getTranslateY() <= 0){
ySpeed = 0;
if(action == Direction.DOWN){ySpeed = speed;}
}
if(snakeHead.getTranslateY() >= HEIGHT - snakeH){
ySpeed = 0;
if(action == Direction.UP){ySpeed = speed;}
}
//TODO: Detect Collisions
if(foodBox.intersects(snakeHead.getTranslateX(),snakeHead.getTranslateY (),snakeW,snakeH)){
newFood();
System.out.println("Collision");
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
root.getChildren().addAll(snakeHead,food);
return root;
}
private void newFood() {
foodX = rand.nextInt(500);
foodY = rand.nextInt(500);
food.setTranslateX(foodX);
food.setTranslateY(foodY);
System.out.println("X " + foodX);
System.out.println("Y " + foodY);
}
private void startGame() {
timeline.play();
}
private void stopGame() {
timeline.stop();
}
#Override
public void start(Stage primaryStage) throws Exception{
window = primaryStage;
mainScene = new Scene(createContent(),WIDTH,HEIGHT);
mainScene.setOnKeyPressed(e-> {
switch(e.getCode()) {
case UP: action = Direction.UP; break;
case DOWN: action = Direction.DOWN; break;
case LEFT: action = Direction.LEFT; break;
case RIGHT: action = Direction.RIGHT; break;
}
});
window.setTitle("Snake");
window.setResizable(false);
window.setScene(mainScene);
window.show();
startGame();
}
public static void main(String[] args) {
launch(args);
}
}
What I'm looking for is when the rectangle hits the apple it relocates. I have been struggling with this for awhile and don't know what to do. Im a fairly new programmer still.
You can check for intersection of snake's and food's boundsInParent.
if(food.getBoundsInParent().intersects(snakeHead.getBoundsInParent())){
newFood();
System.out.println("Collision");
}

Dropped File only moves one bit then exception

So I asked a question about drag and drop last time and thanks to the help I almost got the hang of it. My problem ist after I dragged my rectangle from the left Anchorpane to the right pane, if I try to grab it in the second pane it will only move a few milimeters before showing an InvocationTargetException. Thats my code:
public void smthOver(DragEvent de) {
if (de.getGestureSource() == rect || de.getGestureSource() == ovalo || de.getGestureSource() == strich) {
de.acceptTransferModes(TransferMode.ANY);
de.consume();
} else {
de.acceptTransferModes();
}
public void smthDropped(DragEvent de) {
if (de.getGestureSource() == rect) {
dropZone.getChildren().add(rect);
de.consume();
} else if (de.getGestureSource() == ovalo) {
dropZone.getChildren().add(ovalo);
de.consume();
} else if (de.getGestureSource() == strich) {
dropZone.getChildren().add(strich);
de.consume();
}
}
public void smthDetectedRect(MouseEvent me) {
try {
Dragboard db = rect.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.putString(rect.getId());
db.setContent(content);
me.consume();
} catch (Exception e) {
e.printStackTrace();
}
}
public void smthPressedRect(MouseEvent me) {
x = me.getSceneX();
y = me.getSceneY();
orgTranslateX = ((Rectangle) (me.getSource())).getTranslateX();
orgTranslateY = ((Rectangle) (me.getSource())).getTranslateY();
rect.setCursor(Cursor.HAND);
}
public void smthDraggedRect(MouseEvent me) {
double offsetX = me.getSceneX() - x;
double offsetY = me.getSceneY() - y;
double newTranslateX = orgTranslateX + offsetX;
double newTranslateY = orgTranslateY + offsetY;
((Rectangle) (me.getSource())).setTranslateX(newTranslateX);
((Rectangle) (me.getSource())).setTranslateY(newTranslateY);
Thanks in advance!
Edit: Sorry didnt know i have to show the stacktrace
java.lang.IllegalArgumentException: Children: duplicate children added: parent
= Pane[id=dropZone]
So I understand the exception that I add multiple children with the name "rect" to the Pane in "smthDropped" but you have any Idea how I can fix this? Because I use "smthDropped" to add the Shape from the left pane to the right. Hope this solves the confusion

How to create StackPane on the drawn rectangle area

I'm creating UI editor and for that I need to draw UI components on mouse events. I'm stuck on drawing button with caption inside of it. As a result of my searches over stackoverflow I tried to use StackPane for creating Rectangle with caption.
For layout I'm using Group element. The problem is, when I add StackPane to the Group it's being displayed on the top left corner of the Group. However, if I draw just Rectangle itself, it's being displayed on that place, where I'm releasing the mouse.
How to achieve the same effect for StackPane?
Here is my code:
public class Main extends Application {
double startingPointX, startingPointY;
Group rectanglesGroup = new Group();
Rectangle newRectangle = null;
boolean newRectangleIsBeingDrawn = false;
// the following method adjusts coordinates so that the rectangle
// is shown "in a correct way" in relation to the mouse event
void adjustRectanglePRoperties(double startingPointX,
double startingPointY, double endingPointX, double endingPointY,
Rectangle givenRectangle) {
givenRectangle.setX(startingPointX);
givenRectangle.setY(startingPointY);
givenRectangle.setWidth(endingPointX - startingPointX);
givenRectangle.setHeight(endingPointY - startingPointY);
if (givenRectangle.getWidth() < 0) {
givenRectangle.setWidth(-givenRectangle.getWidth());
givenRectangle.setX(givenRectangle.getX()
- givenRectangle.getWidth());
}
if (givenRectangle.getHeight() < 0) {
givenRectangle.setHeight(-givenRectangle.getHeight());
givenRectangle.setY(givenRectangle.getY()
- givenRectangle.getHeight());
}
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Drawing rectangles");
Scene scene = new Scene(rectanglesGroup, 800, 600);
scene.setFill(Color.BEIGE);
scene.setOnMousePressed(e -> {
if (newRectangleIsBeingDrawn == false) {
startingPointX = e.getSceneX();
startingPointY = e.getSceneY();
newRectangle = new Rectangle();
// a non finished rectangle has always the same color
newRectangle.setFill(Color.SNOW); // almost white color
//Line line = new Line(20,120,270,120);
newRectangle.setStroke(Color.BLACK);
newRectangle.setStrokeWidth(1);
newRectangle.getStrokeDashArray().addAll(3.0, 7.0, 3.0, 7.0);
rectanglesGroup.getChildren().add(newRectangle);
newRectangleIsBeingDrawn = true;
}
});
scene.setOnMouseDragged(e -> {
if (newRectangleIsBeingDrawn == true) {
double currentEndingPointX = e.getSceneX();
double currentEndingPointY = e.getSceneY();
adjustRectanglePRoperties(startingPointX, startingPointY,
currentEndingPointX, currentEndingPointY, newRectangle);
}
});
scene.setOnMouseReleased(e->{
if(newRectangleIsBeingDrawn == true){
//now the drawing of the new rectangle is finished
//let's set the final color for the rectangle
/******************Drawing textbox*******************************/
//newRectangle.setFill(Color.WHITE);
//newRectangle.getStrokeDashArray().removeAll(3.0, 7.0, 3.0, 7.0);
/****************************************************************/
/*****************Drawing button*********************************/
Image image = new Image("file:button.png");
ImagePattern buttonImagePattern = new ImagePattern(image);
newRectangle.setFill(buttonImagePattern);
newRectangle.setStroke(Color.WHITE);
newRectangle.getStrokeDashArray().removeAll(3.0,7.0,3.0,7.0);
Text text = new Text("Button");
rectanglesGroup.getChildren().remove(newRectangle);
StackPane stack = new StackPane();
stack.getChildren().addAll(newRectangle, text);
rectanglesGroup.getChildren().add(stack);
/****************************************************************/
colorIndex++; //index for the next color to use
//if all colors have been used we'll start re-using colors
//from the beginning of the array
if(colorIndex>=rectangleColors.length){
colorIndex=0;
}
newRectangle=null;
newRectangleIsBeingDrawn=false;
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I'm using OnMouseReleased event to create components.
I looked for the setX, setPosition or something like this methods, but couldn't find them in StackPane's methods.
And I don't know how translate methods work. So I didn't try them to achieve my goal.
You should read the documentation about a JavaFX Node.
You can position the nodes absolutely via setLayoutX (and Y) or relative via setTranslateX (and Y), which adds to the current layout position.
A StackPane is just a container and in your case no different to any other Node you want to place on your Scene. Just create it, set the dimensions and location and put it on the Scene.
Your code doesn't work, so I created my own. Here's example code about how to approach this matter:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.StrokeLineCap;
import javafx.stage.Stage;
public class RubberBandSelectionDemo extends Application {
CheckBox drawButtonCheckBox;
public static void main(String[] args) {
launch(args);
}
Pane root;
#Override
public void start(Stage primaryStage) {
root = new Pane();
root.setStyle("-fx-background-color:white");
root.setPrefSize(1024, 768);
drawButtonCheckBox = new CheckBox( "Draw Button");
root.getChildren().add( drawButtonCheckBox);
primaryStage.setScene(new Scene(root, root.getWidth(), root.getHeight()));
primaryStage.show();
new RubberBandSelection(root);
}
public 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);
}
};
EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
// get coordinates
double x = rect.getX();
double y = rect.getY();
double w = rect.getWidth();
double h = rect.getHeight();
if( drawButtonCheckBox.isSelected()) {
// create button
Button node = new Button();
node.setDefaultButton(false);
node.setPrefSize(w, h);
node.setText("Button");
node.setLayoutX(x);
node.setLayoutY(y);
root.getChildren().add( node);
} else {
// create rectangle
Rectangle node = new Rectangle( 0, 0, w, h);
node.setStroke( Color.BLACK);
node.setFill( Color.BLACK.deriveColor(0, 0, 0, 0.3));
node.setLayoutX( x);
node.setLayoutY( y);
root.getChildren().add( node);
}
// remove rubberband
rect.setX(0);
rect.setY(0);
rect.setWidth(0);
rect.setHeight(0);
group.getChildren().remove( rect);
}
};
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());
}
}
};
private final class DragContext {
public double mouseAnchorX;
public double mouseAnchorY;
}
}
}
And here's an image:
The demo shows a rubberband selection which allows you to draw a selection rectangle. Upon release of the mouse button either a rectangle or a button is drawn, depending on the "Draw Button" checkbox selection in the top left corner. If you'd like to draw a StackPane, just change the code accordingly in the mouse released handler.
And of course, if you want to draw the components directly instead of the rubberband, just exchange the Rectangle in the rubberband selection code with e. g. a Button. Here's the Button drawing code only, just replace it in the above example.
public class RubberBandSelection {
final DragContext dragContext = new DragContext();
Button button;
Pane group;
public RubberBandSelection( Pane group) {
this.group = group;
button = new Button();
button.setPrefSize(0, 0);
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();
button.setLayoutX(dragContext.mouseAnchorX);
button.setLayoutY(dragContext.mouseAnchorY);
button.setPrefWidth(0);
button.setPrefHeight(0);
group.getChildren().add( button);
}
};
EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
// get coordinates
double x = button.getLayoutX();
double y = button.getLayoutY();
double w = button.getWidth();
double h = button.getHeight();
// create button
Button node = new Button();
node.setDefaultButton(false);
node.setPrefSize(w, h);
node.setText("Button");
node.setLayoutX(x);
node.setLayoutY(y);
root.getChildren().add( node);
// remove rubberband
button.setLayoutX(0);
button.setLayoutY(0);
button.setPrefWidth(0);
button.setPrefHeight(0);
group.getChildren().remove( button);
}
};
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)
button.setPrefWidth( offsetX);
else {
button.setLayoutX(event.getSceneX());
button.setPrefWidth(dragContext.mouseAnchorX - button.getLayoutX());
}
if( offsetY > 0) {
button.setPrefHeight( offsetY);
} else {
button.setLayoutY(event.getSceneY());
button.setPrefHeight(dragContext.mouseAnchorY - button.getLayoutY());
}
}
};
private final class DragContext {
public double mouseAnchorX;
public double mouseAnchorY;
}
}

How to resize Javafx undecorated stage?

I am new to JavaFX technology, currently I am working on javafx application, in which there is undecorated stage,I am able to move it on screen using below code , but I am not able to resize this window from bottom right corner, can anyone suggest me the solution.
public void loadPanel(final Stage stage) {
myPane.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
xOffset = event.getSceneX();
yOffset = event.getSceneY();
}
});
myPane.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
stage.setX(event.getScreenX() - xOffset);
stage.setY(event.getScreenY() - yOffset);
}
});
this.stage = stage;
this.stage.initStyle(StageStyle.UNDECORATED);
this.stage.setScene(scene);
this.stage.show();
}
If you want to resize your stage only on bottom right corner, you need at first an if statement to check, whether your mouse is there. In addition to this you need to distinguish in your dragFunction whether this is the case or not. If this is the case, you need the value your mouse moved and add this to the actuall size of your stage. The value -10 in the code (setOnMousePressed) is like a border so that you have a bigger area where you can click to resize the window. You can adjust this value like you want.
This code snippets may be helpful:
private Boolean resizebottom = false;
private double dx;
private double dy;
myPane.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
if (event.getX() > stage.getWidth() - 10
&& event.getX() < stage.getWidth() + 10
&& event.getY() > stage.getHeight() - 10
&& event.getY() < stage.getHeight() + 10) {
resizebottom = true;
dx = stage.getWidth() - event.getX();
dy = stage.getHeight() - event.getY();
} else {
resizebottom = false;
xOffset = event.getSceneX();
yOffset = event.getSceneY();
}
}
});
myPane.setOnMouseDragged(new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
if (resizebottom == false) {
stage.setX(event.getScreenX() - xOffset);
stage.setY(event.getScreenY() - yOffset);
} else {
stage.setWidth(event.getX() + dx);
stage.setHeight(event.getY() + dy);
}
}
});
you can make your stage public static and use this code and customize as per your code:
stage1.setWidth(Your double value);
stage1.setHeight(Your double value);

Resources