Drawing rounded rectangle while dragging fails - javafx

I am trying to draw a simple rectangle with rounded corners in javafx while dragging the mouse.
First issue: I can't make the upper-left corner rounded.
Second issue: I want my application to be able to draw nice and full rounded rectangles not like the second one from my picture.
Please, how can I fix these?
Thanks in advance for your help.
Here is my code:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage stage){
stage.setTitle("Test");
root = new BorderPane();
Scene scene = new Scene(root, 400, 400);
paintings = new Group();
stage.setScene(scene);
canvas = new Rectangle(0, 0, stage.getScene().getWidth(), stage.getScene().getHeight());
canvas.setFill(Color.WHITE);
addHandlers();
root.setCenter(canvas);
root.getChildren().add(paintings);
stage.show();
}
private void paintRectangle(){
roundedRect = new Rectangle(pressedX,
pressedY,
draggedX - pressedX,
draggedY - pressedY);
roundedRect.setFill(Color.RED);
roundedRect.setArcHeight(40);
roundedRect.setArcWidth(40);
paintings.getChildren().add(roundedRect);
}
private void addHandlers(){
canvas.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent me) {
pressedX = me.getX();
pressedY = me.getY();
}
});
canvas.setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent me) {
/* If I make the drawing in here, I get round corners, but it doesn't get drawn while dragging*/
//paintRectangle();
}
});
canvas.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent me) {
draggedX = me.getX();
draggedY = me.getY();
paintRectangle();
}
});
}
double pressedX, pressedY;
double draggedX, draggedY;
Rectangle canvas;
Group paintings;
Rectangle roundedRect;
BorderPane root;
}
And here is my picture:

I could not examine your code but here is an alternative approach. You may merge this with your code:
import javafx.application.Application;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Daer extends Application {
BorderPane pane;
Rectangle rect;
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);
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);
stage.show();
}
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());
} 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);
r.setArcHeight(40);
r.setArcWidth(40);
return r;
}
public static void main(String[] args) {
launch(args);
}
}

Related

How to stop transition when checkbox is unchecked javafx

So I've made a checkbox that applies a scale transition to a rectangle when checked. But the problem is that the transition keeps going even after I uncheck the checkbox. Any ideas on how to make it stop after un-checking?
checkbox.setOnAction(e -> {
ScaleTransition scaleT = new ScaleTransition(Duration.seconds(5), rectangle);
scaleT.setAutoReverse(true);
scaleT.setCycleCount(Timeline.INDEFINITE);
scaleT.setToX(2);
scaleT.setToY(2);
scaleT.play();
});
To control the animation, you need to define the transistion(with INDEFINITE cycle count) outside the CheckBox listener/action. Then you can just play/pause the animation as you required.
Below is the quick demo:
import javafx.animation.ScaleTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
import javafx.util.Duration;
public class ScaleTransitionDemo extends Application {
#Override
public void start(Stage stage) {
Shape rectangle = new Rectangle(50, 50, Color.BLUE);
ScaleTransition transition = new ScaleTransition(Duration.seconds(1), rectangle);
transition.setDuration(Duration.seconds(1));
transition.setAutoReverse(true);
transition.setCycleCount(Timeline.INDEFINITE);
transition.setToX(3);
transition.setToY(3);
CheckBox checkBox = new CheckBox("Animate");
checkBox.selectedProperty().addListener((obs, old, selected) -> {
if (selected) {
transition.play();
} else {
transition.pause();
}
});
StackPane pane = new StackPane(rectangle);
VBox.setVgrow(pane, Priority.ALWAYS);
VBox root = new VBox(20, checkBox, pane);
root.setPadding(new Insets(10));
Scene scene = new Scene(root, 300, 300);
stage.setScene(scene);
stage.setTitle("Scale transition");
stage.show();
}
public static void main(String[] args) {
launch();
}
}
checking whether checkbox is selected or not with .isSelected() method . In this approach , scaled node will back to xy = 1 scale if checkbox is unchecked , but it will be disabled until transition ends .You can adjust setDuration . I've changed it just for gif recording. This is a single class javafx app you can try .
App.java
public class App extends Application {
#Override
public void start(Stage stage) {
Shape rectangle = new Rectangle(50, 50, Color.BLUE);
ScaleTransition scaleT = new ScaleTransition(Duration.seconds(1), rectangle);
CheckBox checkBox = new CheckBox("scale");
checkBox.setOnAction(e -> {
if (checkBox.isSelected()) {
scaleT.setDuration(Duration.seconds(1));
scaleT.setAutoReverse(true);
scaleT.setCycleCount(Timeline.INDEFINITE);
scaleT.setToX(2);
scaleT.setToY(2);
scaleT.play();
} else {
scaleT.setDuration(scaleT.getCurrentTime());
scaleT.stop();
scaleT.setCycleCount(1);
scaleT.setToX(1);
scaleT.setToY(1);
scaleT.play();
checkBox.setDisable(true);
scaleT.setOnFinished((t) -> {
checkBox.setDisable(false);
});
}
});
var scene = new Scene(new HBox(50, rectangle, checkBox), 640, 480);
stage.setScene(scene);
stage.setTitle("scale transition");
stage.show();
}
public static void main(String[] args) {
launch();
}
}

How to set popup scene mouse transparent in javafx

How to do that in JavaFX?
The popup shows up when the mouse enters a node. When the mouse enters the showing popup, the popup obscures the mouse from the node. Then the node fire exit event. How to make the popup ignore the mouse events?
code
package sample;
import javafx.application.Application;
import javafx.geometry.Point3D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
primaryStage.setScene(new Scene(root, 300, 275));
Label labelNode = new Label("Label Node");
labelNode.setPrefHeight(200);
labelNode.styleProperty().set("-fx-background-color: orange");
Popup popup = new Popup();
popup.getScene().getRoot().setMouseTransparent(true);
AnchorPane popContent =new AnchorPane();
popContent.styleProperty().set("-fx-background-color: red");
popContent.setPrefHeight(100);
popContent.getChildren().add(new Label("Popup content"));
popup.getContent().add(popContent);
labelNode.setOnMouseEntered(event->{
Point3D point3D = labelNode.localToScene(event.getX(), event.getY(), 0);
popup.show(primaryStage, point3D.getX()-5, point3D.getY()-5);
});
labelNode.setOnMouseExited(event->{
popup.hide();
});
root.getChildren().add(labelNode);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Please try moving the cursor in to "yellow" several times.
Solution:
Keep two boolean nodeExited and popupExited statuses. Hide popup when both are true.
package sample;
import javafx.application.Application;
import javafx.geometry.Point3D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;
public class Main extends Application {
boolean nodeExited = false;
boolean popupExited = false;
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
primaryStage.setScene(new Scene(root, 300, 275));
Label labelNode = new Label("Label Node");
labelNode.setPrefHeight(200);
labelNode.styleProperty().set("-fx-background-color: orange");
Popup popup = new Popup();
popup.getScene().getRoot().setMouseTransparent(true);
AnchorPane popContent = new AnchorPane();
popContent.styleProperty().set("-fx-background-color: red");
popContent.setPrefHeight(100);
popContent.getChildren().add(new Label("Popup content"));
popup.getContent().add(popContent);
popup.getScene().setOnMouseEntered(event -> {
popupExited = false;
});
popup.getScene().setOnMouseExited(event -> {
popupExited = true;
if (nodeExited)
popup.hide();
});
labelNode.setOnMouseEntered(event -> {
nodeExited = false;
Point3D point3D = labelNode.localToScene(event.getX(), event.getY(), 0);
popup.show(primaryStage, point3D.getX() - 5, point3D.getY() - 5);
});
labelNode.setOnMouseExited(event -> {
nodeExited = true;
if (popupExited)
popup.hide();
});
root.getChildren().add(labelNode);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

JavaFX - StackPane with Pane as EventDispatcher

In the event dispatcher pane occurs an mouse pressed event.
The pane one should show the context menu of it's combobox when a event occurs.
That works fine if the event is only dipatched to pane one.
When the event is dipatched to pane one and pane two the context menu of pane one doesn't show up.
I suppose it has something to do with the event tail and event consuming.
Until now i doesn't had a look at the EventDispatcher Class of the JDK itself.
Here is what i got so far:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
*
* #author Robert
*/
public class EventDispatcherExample extends Application {
private Group root;
private StackPane cStackPane;
private Pane cPaneEventDispatcher;
private Pane cPaneOne;
private ComboBox cComboBox;
private Pane cPaneTwo;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
root = new Group();
cStackPane = new StackPane();
cStackPane.setPrefHeight(200.0);
cStackPane.setPrefWidth(200.0);
cPaneEventDispatcher = new Pane();
cPaneEventDispatcher.setPrefHeight(200.0);
cPaneEventDispatcher.setPrefWidth(200.0);
cPaneEventDispatcher.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
//System.out.println("Mouse pressed in Pane ED.");
cPaneOne.fireEvent(event);
cPaneTwo.fireEvent(event);
}
});
cPaneOne = new Pane();
cPaneOne.setPrefHeight(200.0);
cPaneOne.setPrefWidth(200.0);
cPaneOne.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
//System.out.println("Mouse pressed in Pane One.");
cComboBox.show();
}
});
ObservableList<String> observableList = FXCollections.observableArrayList();
observableList.add("1");
observableList.add("2");
observableList.add("3");
cComboBox = new ComboBox();
cComboBox.setLayoutX(50.0);
cComboBox.setLayoutY(50.0);
cComboBox.setPrefHeight(30.0);
cComboBox.setPrefWidth(100.0);
cComboBox.setItems(observableList);
cPaneTwo = new Pane();
cPaneTwo.setPrefHeight(200.0);
cPaneTwo.setPrefWidth(200.0);
cPaneTwo.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
//System.out.println("Mouse pressed in Pane Two.");
//Something will happen because of selected item in Combo Box of pane one...
}
});
cPaneOne.getChildren().add(cComboBox);
// add the nodes in reverse order
cStackPane.getChildren().add(cPaneTwo);
cStackPane.getChildren().add(cPaneOne);
cStackPane.getChildren().add(cPaneEventDispatcher);
root.getChildren().add(cStackPane);
Scene scene = new Scene(root, 200, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Any ideas how to handle this?
After some ideas I got a solution that at least works:
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
/**
*
* #author Robert
*/
public class EventDispatcherExample extends Application {
private Group root;
private StackPane cStackPane;
private Pane cPaneEventDispatcher;
private Pane cPaneOne;
private ComboBox cComboBox;
private boolean cComboBoxClicked = false;
private Pane cPaneTwo;
public static void main(String[] args) {
launch(args);
}
public boolean isComboBoxClicked() {
if (cComboBoxClicked == true) {
cComboBox.show();
} else {
cComboBox.hide();
}
return cComboBoxClicked;
}
#Override
public void start(Stage primaryStage) throws Exception {
root = new Group();
cStackPane = new StackPane();
cStackPane.setPrefHeight(200.0);
cStackPane.setPrefWidth(200.0);
cPaneEventDispatcher = new Pane();
cPaneEventDispatcher.setPrefHeight(200.0);
cPaneEventDispatcher.setPrefWidth(200.0);
cPaneEventDispatcher.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
//System.out.println("Mouse pressed in Pane ED.");
cPaneOne.fireEvent(event);
cPaneTwo.fireEvent(event);
}
});
cPaneOne = new Pane();
cPaneOne.setPrefHeight(200.0);
cPaneOne.setPrefWidth(200.0);
cPaneOne.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
//System.out.println("Mouse pressed in Pane One.");
Rectangle rect = new Rectangle(cComboBox.getLayoutX(), cComboBox.getLayoutY(),
cComboBox.getPrefWidth(), cComboBox.getPrefHeight());
cComboBoxClicked = rect.contains(event.getX(), event.getY());
}
});
ObservableList<String> observableList = FXCollections.observableArrayList();
observableList.add("1");
observableList.add("2");
observableList.add("3");
cComboBox = new ComboBox();
cComboBox.setLayoutX(50.0);
cComboBox.setLayoutY(50.0);
cComboBox.setPrefHeight(30.0);
cComboBox.setPrefWidth(100.0);
cComboBox.setItems(observableList);
cComboBox.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
// if cComboBoxSelectedIndex == 1 do Color on pane two
// if cComboBoxSelectedIndex == 2 do Size on pane two
// if cComboBoxSelectedIndex == 3 do ...
//System.out.println("newValue " + newValue);
}
});
cPaneTwo = new Pane();
cPaneTwo.setPrefHeight(200.0);
cPaneTwo.setPrefWidth(200.0);
cPaneTwo.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
//System.out.println("Mouse pressed in Pane Two.");
boolean cComboBoxClicked = isComboBoxClicked();
if (cComboBoxClicked){
//System.out.println("Skip code internally managed by pane two.");
return;
}
// Internal code of pane two
//...
}
});
cPaneOne.getChildren().add(cComboBox);
// add the nodes in reverse order
cStackPane.getChildren().add(cPaneTwo);
cStackPane.getChildren().add(cPaneOne);
cStackPane.getChildren().add(cPaneEventDispatcher);
root.getChildren().add(cStackPane);
Scene scene = new Scene(root, 200, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Perhaps a better approach comes up during the time of someone else.
Am looking forward...

How to clip and resize javafx borderpane

I am just starting with JavaFX. I want to have a BorderPane with controls on top, left, and right, and an image in the center. I want the center pane to resize as you resize the window, but to always be able to see all left, right, and top controls.
With the code below, I can show a button in the left, top, and right. And I can display an image in the center.
But the image expands beyond center bounds and hides the right button.
Oddly, if I set a clipping rectangle on the imageview in the center pane (uncomment lines 67 & 68), it does in fact only draw the clipped region, but the rest of the layout behaves as if it were drawing the whole picture. That is, the UNDRAWN part of the image still obscures the button on the right.
Any help would be much appreciated.
Thanks in advance and apologies if it's simple.
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class ImageApp extends Application {
private BorderPane root;
private Rectangle clipRect;
private ImageView iv;
private StackPane leftPane;
private StackPane rightPane;
private Button topButton;
private Button leftButton;
private Button rightButton;
#Override
public void start(Stage primaryStage) {
root = new BorderPane();
Scene primaryScene = new Scene(root, 900, 800);
initializePrimaryStage(primaryStage, primaryScene);
initializeFrameContent(root, topButton, leftButton);
initializeContent(root);
primaryStage.show();
}
private void initializeFrameContent(BorderPane root, Button topButton, Button leftButton) {
topButton = new Button("TOP");
leftButton = new Button("LEFT");
rightButton = new Button("RIGHT");
leftPane = new StackPane(leftButton);
leftPane.setAlignment(Pos.TOP_LEFT);
rightPane = new StackPane(rightButton);
rightPane.setAlignment(Pos.TOP_RIGHT);
root.setLeft(leftPane);
root.setTop(topButton);
root.setRight(rightButton);
}
private void initializePrimaryStage(Stage primaryStage, Scene primaryScene) {
primaryStage.setTitle("Image Clip Test");
primaryStage.setScene(primaryScene);
primaryStage.setWidth(400);
primaryStage.setHeight(300);
primaryStage.minWidthProperty().setValue(400);
primaryStage.minHeightProperty().setValue(300);
}
public static void main(String[] args) {
launch(args);
}
private void initializeContent(BorderPane root) {
Image image = new Image(
"http://www.ciee.org/study-abroad/images/cities/0020/headers/desktop/big-ben-london-traffic-trafalgar-abroad-studies.jpg"
);
iv = new ImageView(image);
root.setCenter(iv);
//clipRect = new Rectangle(400,200);
//root.getCenter().setClip(clipRect);
}
}
You don't specify what you intend to do. Why would you want to clip the content? The way you describe it all you want is some background that's getting clipped. You can do that with various mechanisms, e. g. css.
Or you could use a proper parent, e. g. a ScrollPane in order to limit the region or e. g. an ImageViewPane in order to stretch to fit:
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class ImageApp extends Application {
private BorderPane root;
private Rectangle clipRect;
private ImageView iv;
private StackPane leftPane;
private StackPane rightPane;
private Button topButton;
private Button leftButton;
private Button rightButton;
#Override
public void start(Stage primaryStage) {
root = new BorderPane();
Scene primaryScene = new Scene(root, 900, 800);
initializePrimaryStage(primaryStage, primaryScene);
initializeFrameContent(root, topButton, leftButton);
initializeContent(root);
primaryStage.show();
}
private void initializeFrameContent(BorderPane root, Button topButton, Button leftButton) {
topButton = new Button("TOP");
leftButton = new Button("LEFT");
rightButton = new Button("RIGHT");
leftPane = new StackPane(leftButton);
leftPane.setAlignment(Pos.TOP_LEFT);
rightPane = new StackPane(rightButton);
rightPane.setAlignment(Pos.TOP_RIGHT);
root.setLeft(leftPane);
root.setTop(topButton);
root.setRight(rightButton);
}
private void initializePrimaryStage(Stage primaryStage, Scene primaryScene) {
primaryStage.setTitle("Image Clip Test");
primaryStage.setScene(primaryScene);
primaryStage.setWidth(400);
primaryStage.setHeight(300);
primaryStage.minWidthProperty().setValue(400);
primaryStage.minHeightProperty().setValue(300);
}
public static void main(String[] args) {
launch(args);
}
private void initializeContent(BorderPane root) {
Image image = new Image(
"http://www.ciee.org/study-abroad/images/cities/0020/headers/desktop/big-ben-london-traffic-trafalgar-abroad-studies.jpg"
);
iv = new ImageView(image);
// ImageViewPane content = new ImageViewPane( iv);
ScrollPane content = new ScrollPane( imageView);
// hide scrollbars
content.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
content.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
content.setPadding(Insets.EMPTY);
root.setCenter(content);
}
// code from here: https://stackoverflow.com/questions/22993550/how-to-resize-an-image-when-resizing-the-window-in-javafx
class ImageViewPane extends Region {
private ObjectProperty<ImageView> imageViewProperty = new SimpleObjectProperty<ImageView>();
public ObjectProperty<ImageView> imageViewProperty() {
return imageViewProperty;
}
public ImageView getImageView() {
return imageViewProperty.get();
}
public void setImageView(ImageView imageView) {
this.imageViewProperty.set(imageView);
}
public ImageViewPane() {
this(new ImageView());
}
#Override
protected void layoutChildren() {
ImageView imageView = imageViewProperty.get();
if (imageView != null) {
imageView.setFitWidth(getWidth());
imageView.setFitHeight(getHeight());
layoutInArea(imageView, 0, 0, getWidth(), getHeight(), 0, HPos.CENTER, VPos.CENTER);
}
super.layoutChildren();
}
public ImageViewPane(ImageView imageView) {
imageViewProperty.addListener(new ChangeListener<ImageView>() {
#Override
public void changed(ObservableValue<? extends ImageView> arg0, ImageView oldIV, ImageView newIV) {
if (oldIV != null) {
getChildren().remove(oldIV);
}
if (newIV != null) {
getChildren().add(newIV);
}
}
});
this.imageViewProperty.set(imageView);
}
}
}

Node order in the stage (Javafx)

With following code (JavaFX 8) I get 4 rectangles (Cards). The rectangles were displayed with 15px shift. Last card is on the top of the Deck. How can I take with the right mouse event another cards to the top?
Another words, how can I primaryStage rebuild?
package application;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.ImagePattern;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Main extends Application {
private static ObservableList<Rectangle> cardList = FXCollections.observableArrayList();
public static Rectangle getCard(int i) {
Image card = new Image("file:C:\\Workspace\\pic\\" + i + "_12.png");
Rectangle rect = new Rectangle(100 + i * 15, 120, 71, 96);
rect.setFill(new ImagePattern(card));
rect.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
if (t.getButton().equals(MouseButton.SECONDARY)) {
rect.setStrokeWidth(2);
rect.setStroke(Color.YELLOW);
}
}
});
rect.setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
if (t.getButton().equals(MouseButton.SECONDARY)) {
rect.setStrokeWidth(0);
}
}
});
return rect;
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("4 cards");
Group root = new Group();
Scene scene = new Scene(root, 300, 300);
for (int i = 0; i < 4; i++) {
cardList.add(getCard(i));
}
for (int i = 0; i < 4; i++) {
root.getChildren().addAll(cardList.get(i));
}
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Resources