I have to create a "slot machine effect": I have a root layer an on it I have 3 Rectangles, each one in a TilePane cell. i tryed to add an event handler that should modify the rect (resizing it and rotating it) in order to change the figure that it displays. Unfortunately, my figure is never at the center fo its cell. How can I fix it?
package test;
import java.util.Random;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.TilePane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
/**
*
* #author bog
*/
public class Test extends Application {
StackPane root = new StackPane();
TilePane tp = new TilePane(Orientation.HORIZONTAL);
#Override
public void start(Stage primaryStage) {
//root.getChildren().add(btn);
for(int i = 0; i < 3 ; i++){
final Rectangle r = new Rectangle(100, 100, Color.GREY);
r.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
Random rnd = new Random();
int n = rnd.nextInt(5);
if(n == 0){ // horizontal line
r.setWidth(100);
r.setHeight(5);
System.out.println("Linea orizontale");
}
if(n == 1){ // vertical line
r.setWidth(5);
r.setHeight(100);
System.out.println("Linea verticale");
}
if(n == 2){ // rombo
r.getTransforms().add(new Rotate(45,50,50));
System.out.println("rombo");
}
if(n == 3){ // back-slash line
r.setWidth(5);
r.setHeight(100);
r.getTransforms().add(new Rotate(45,50,50));
System.out.println("Linea /");
}
if(n == 4){ // slash line
r.setWidth(100);
r.setHeight(5);
r.getTransforms().add(new Rotate(45,50,50));
System.out.println("Linea \\");
}
}
});
final StackPane sp = new StackPane();
sp.getChildren().add(r);
tp.getChildren().add(sp);
}
tp.setAlignment(Pos.CENTER);
root.getChildren().add(tp);
Scene scene = new Scene(root, 500, 450);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
i am not quite sure what is your problem , and right now i cant test your code , but almost every time i got alignment issues i fix them with scene builder, where i create the static components by hand , which will be rendered allright , and inside them i place the dynamic components. So your pane could be made from scene builder starting with a basic anchor pane and inside it place 3 panes with your default width, and inside them dynamically add the images you wish each time.
hope it helps...
Related
I am using CSS to configure my JavaFX Sliders, then applying the style in code with:
cssSlider.getStyleClass().add("slider-style");
When I first open my window, the tick marks are present on the CSS configured Slider(s). When I close and reopen the window, the tick marks are no longer present.
This following example demonstrates the anomaly using 2 Sliders, one configured directly, the other via CSS. Click the button to hide the window for 2 seconds. Notice that the Slider in which I directly configure the attributes works fine after hiding and re-showing, but the CSS configured Slider loses its tick marks after hiding and re-showing.
Does anyone have any ideas why showing, hiding, and re-showing the window causes the tick marks to vanish from the CSS configured Slider? Am I doing something wrong, or is this a JavaFX bug?
sample.css:
.slider-style {
-fx-show-tick-marks: true;
-fx-snap-to-ticks: true;
-fx-major-tick-unit: 5;
-fx-minor-tick-count: 5;
}
CssExample.java:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
/**
* This simple example demonstrates that JavaFX Sliders configured with CSS only show their tick marks the first time
* they are shown. If the Slider is hidden, then shown again, the tick marks are gone forever.
*/
public class CssExample extends Application {
#Override
public void start(Stage stage) throws InterruptedException, IOException {
Group root = new Group();
Scene scene = new Scene(root, 400, 200);
stage.setScene(scene);
stage.setTitle("Slider Sample");
scene.setFill(Color.BLACK);
GridPane grid = new GridPane();
grid.setPadding(new Insets(10, 10, 10, 10));
grid.setVgap(10);
grid.setHgap(70);
scene.setRoot(grid);
int rowNumber = 1;
Label directLabel = new Label("Slider from attribute assignment");
GridPane.setConstraints(directLabel, 1, rowNumber++);
grid.getChildren().add(directLabel);
Slider directSlider = new Slider();
GridPane.setConstraints(directSlider, 1, rowNumber++);
grid.getChildren().add(directSlider);
directSlider.setShowTickMarks(true);
directSlider.setSnapToTicks(true);
directSlider.setMajorTickUnit(5);
directSlider.setMinorTickCount(5);
Label cssLabel = new Label("Slider from CSS (tick marks disappear after hidden)");
GridPane.setConstraints(cssLabel, 1, rowNumber++);
grid.getChildren().add(cssLabel);
Slider cssSlider = new Slider();
GridPane.setConstraints(cssSlider, 1, rowNumber++);
grid.getChildren().add(cssSlider);
URL url = getClass().getResource("sample.css");
String cssString = url.toExternalForm();
scene.getStylesheets().add(cssString);
cssSlider.getStyleClass().add("slider-style");
Button button = new Button("Hide for 2 Seconds");
GridPane.setConstraints(button, 1, rowNumber++);
grid.getChildren().add(button);
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
stage.hide();
stage.show();
}
});
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
is this a JavaFX bug?
Yes.
See: https://github.com/openjdk/jfx/blob/fdc88341f1df8fb9c99356ada54b25124b77ea6e/modules/javafx.controls/src/main/java/javafx/scene/control/skin/SliderSkin.java#L398
It is a bug in the internal implementation of the setShowTickMarks method of SliderSkin (verified in JavaFX 18.0.1).
Test case:
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.io.IOException;
public class CssExample extends Application {
private static final String CSS = // language=CSS
"""
.slider-style {
-fx-show-tick-marks: true;
-fx-snap-to-ticks: true;
-fx-major-tick-unit: 5;
-fx-minor-tick-count: 5;
}
""";
private static final String CSS_INLINE = "data:text/css," + CSS;
#Override
public void start(Stage stage) throws InterruptedException, IOException {
Platform.setImplicitExit(false);
Slider cssSlider = new Slider();
cssSlider.showTickMarksProperty().addListener((observable, oldValue, newValue) ->
System.out.println(cssSlider.showTickMarksProperty())
);
cssSlider.getStyleClass().add("slider-style");
PauseTransition hideAnimation = new PauseTransition(Duration.seconds(2));
hideAnimation.setOnFinished(e -> stage.show());
Button hideWindow = new Button("Hide for 2 Seconds");
hideWindow.setOnAction(e -> {
stage.hide();
hideAnimation.play();
});
Button closeApp = new Button("Close app");
closeApp.setOnAction(e -> Platform.exit());
VBox layout = new VBox(
10,
cssSlider, hideWindow, closeApp
);
layout.setPadding(new Insets(10));
layout.setPrefSize(400, 120);
Scene scene = new Scene(layout);
scene.getStylesheets().add(CSS_INLINE);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Test output:
BooleanProperty [bean: Slider#132908b9[styleClass=slider slider-style], name: showTickMarks, value: true]
BooleanProperty [bean: Slider#132908b9[styleClass=slider slider-style], name: showTickMarks, value: false]
BooleanProperty [bean: Slider#132908b9[styleClass=slider slider-style], name: showTickMarks, value: true]
It switches showTicks from true to false, and back to true, which triggers the bug.
In the current implementation for the setShowTicks method:
private void setShowTickMarks(boolean ticksVisible, boolean labelsVisible) {
showTickMarks = (ticksVisible || labelsVisible);
Slider slider = getSkinnable();
if (showTickMarks) {
if (tickLine == null) {
tickLine = new NumberAxis();
tickLine.setAutoRanging(false);
tickLine.setSide(slider.getOrientation() == Orientation.VERTICAL ? Side.RIGHT : (slider.getOrientation() == null) ? Side.RIGHT: Side.BOTTOM);
tickLine.setUpperBound(slider.getMax());
tickLine.setLowerBound(slider.getMin());
tickLine.setTickUnit(slider.getMajorTickUnit());
tickLine.setTickMarkVisible(ticksVisible);
tickLine.setTickLabelsVisible(labelsVisible);
tickLine.setMinorTickVisible(ticksVisible);
// add 1 to the slider minor tick count since the axis draws one
// less minor ticks than the number given.
tickLine.setMinorTickCount(Math.max(slider.getMinorTickCount(),0) + 1);
if (slider.getLabelFormatter() != null) {
tickLine.setTickLabelFormatter(stringConverterWrapper);
}
getChildren().clear();
getChildren().addAll(tickLine, track, thumb);
} else {
tickLine.setTickLabelsVisible(labelsVisible);
tickLine.setTickMarkVisible(ticksVisible);
tickLine.setMinorTickVisible(ticksVisible);
}
}
else {
getChildren().clear();
getChildren().addAll(track, thumb);
// tickLine = null;
}
getSkinnable().requestLayout();
}
The first time it shows the ticks it will do this:
getChildren().clear();
getChildren().addAll(tickLine, track, thumb);
Then, when the ticks are hidden, it will do this:
getChildren().clear();
getChildren().addAll(track, thumb);
Then, when the ticks are supposed to be shown again, the tickLine is not added back to the children, so it never shows the ticks again.
This program first displays a bullseye created by three different sized circles.
Once the animate me button is clicked, the function animation() will make the existing circles shrink inwards until the size of the circles is zero.
Once the user presses the button named "Press to stop", the animation will then stop. If the user presses the button again, it will then keep going from the state it was stopped from, so on so forth.
Currently, this is not working as intended. It only creates about 9 circles (including the nine circles that the program began with). I know I will need to use the action listener in order to make the program run, but I'm having a hard time in terms of the documentation of the action listener. What am I supposed to put in the parameters of the listener? If you see any other ways around this, please feel free to let me know.
package target;
import javafx.animation.ScaleTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Target extends Application
{
Circle[] cir = new Circle[7];
Button btn = new Button("Animate me!");
StackPane root = new StackPane();
public static void main(String[] args)
{
launch(args);
}
/**
* start method will create the target and the start button first
* displayed on-screen to the user
*/
#Override
public void start(Stage primaryStage)
{
root.setStyle("-fx-border-color:black;");
cir[0] = new Circle(400, 250, 200);
cir[0].setFill(Color.RED);
cir[0].setStyle("-fx-border-color:black;");
cir[1] = new Circle(315, 165, 115);
cir[1].setFill(Color.WHITE);
cir[1].setStyle("-fx-border-color:black;");
cir[2] = new Circle(230, 80, 30);
cir[2].setFill(Color.RED);
cir[2].setStyle("-fx-border-color:black;");
root.getChildren().addAll(cir[0], cir[1], cir[2]);
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root));
primaryStage.show();
btn.setOnAction(e ->
{
animation();
btn.setText("Press to Stop");
});
}
public void animation()
{
//Timeline animation = new Timeline(
//)
ScaleTransition[] st = new ScaleTransition[7];
boolean recycleCircles = false;
st[0]= new ScaleTransition(Duration.seconds(7), cir[0]);
st[0].setToX(0.0f);
st[0].setToY(0.0f);
st[0].play();
st[1] = new ScaleTransition(Duration.seconds(5.5), cir[1]);
st[1].setToX(0.0f);
st[1].setToY(0.0f);
st[1].play();
st[2] = new ScaleTransition(Duration.seconds(4), cir[2]);
st[2].setToX(0.0f);
st[2].setToY(0.0f);
st[2].play();
// int delayInc = 1;
int delay = 1;
//will create circles (will rotate between white and red) and then add
//to scaleTransitions
//while(btn.isPressed() == false)
{
for(int i = 3; i<st.length; i++)
{
if(recycleCircles == true)
{
i = 0;
recycleCircles = false;
}
if(i % 2 == 1)
{
cir[i] = new Circle(400,250,200);
cir[i].setFill(Color.WHITE);
cir[i].setStyle("-fx-border-color:black;");
root.getChildren().add(cir[i]);
cir[i].toBack();
st[i] = new ScaleTransition(Duration.seconds(7), cir[i]);
st[i].setDelay(Duration.seconds(delay));
delay++;
st[i].setToX(0.0f);
st[i].setToY(0.0f);
st[i].play();
}
else if(i%2==0)
{
cir[i] = new Circle(400, 250, 200);
cir[i].setFill(Color.RED);
cir[i].setStyle("-fx-border-color:black;");
root.getChildren().add(cir[i]);
cir[i].toBack();
st[i] = new ScaleTransition(Duration.seconds(7), cir[i]);
st[i].setDelay(Duration.seconds(delay));
delay++;
st[i].setToX(0.0f);
st[i].setToY(0.0f);
st[i].play();
}
if(i == 6)
recycleCircles = true;
}
}
//btn.pressedProperty().addListener(listener);
btn.setOnMousePressed(event ->
{
});
btn.setOnMouseReleased(event ->
{
for(int y = 0; y<st.length;y++)
{
}
});
}
}
Not sure whether you have any specific use case with each circle. If your are using the circles only for the purpose of alternating row colors, then you can get similar effect with radial gradient's repeat option.
To the extent I understand the question, below program is what I can think of. May be this can help you.
Just to let you know, the overall effect is slightly different from your program. The main difference in effects is, your program gives an effect/impression that each circle are shrinking towards center, as the distance between each circle is always same till it shrinked completely.
My program gives the effect/.impression like the entire board is moving away from your sight till it vanishes. In my program the distance between each circle decreases proportianally till it shrinks.
import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TargetAnimation extends Application {
Button btn = new Button("Animate me!");
StackPane root = new StackPane();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
root.setPrefSize(400, 400);
root.setStyle("-fx-border-color:black;");
Circle board = new Circle();
board.setRadius(200);
board.setStyle("-fx-fill:radial-gradient(focus-angle 0deg , focus-distance 0% , center 50% 50% , radius 21% , repeat, red 44% , white 46% );-fx-stroke-width:1px;-fx-stroke:black;");
root.getChildren().addAll(board, btn);
primaryStage.setScene(new Scene(root));
primaryStage.show();
ScaleTransition transition = new ScaleTransition(Duration.seconds(7), board);
transition.setToX(0);
transition.setToY(0);
btn.setOnAction(e -> {
switch (transition.getStatus()) {
case RUNNING:
transition.pause();
break;
case PAUSED:
transition.play();
break;
default:
board.setScaleX(1);
board.setScaleY(1);
transition.playFromStart();
}
});
}
}
The code given to setOnAction is an EventHandler, which is a #FunctionalInterface with the single method handle. That means that you can give it a lambda expression instead. The method takes an argument, which is the ActionEvent of clicking the button (created for you by JavaFX), and runs the code you give it.
If you want to pause the animation, call Animation#pause, and if you want to resume it, call Animation#play. I suggest that you create a ParallelTransition with all of your ScaleTransitions as its children. Then call the above methods on the ParallelTransition in the event handler.
That means that the setup code, like naming the button and creates the animations, goes outside of the event handler.
For the life of me, I can't seem to get help on this. I have a JavaFX screen and I am trying to get to show fullscreen on my 2nd monitor. I tried the following based on other recommendations but to no avail. I know the coordinates are right but it KEEPS going full screen on my MAIN monitor. Please help.
if (mainSet.getBoolean("fullScr", false)) {
int count = mainSet.getInt("MonSel", 0);
if (count > 0) {
int i = 0;
for (Screen screen: Screen.getScreens()) {
if (count == i) {
Rectangle2D bounds = screen.getBounds();
primaryStage.setX(bounds.getMinX());
System.out.println(bounds.getMinX());
System.out.println(bounds.getMinY());
primaryStage.setY(bounds.getMinY());
}
i++;
}
}
primaryStage.setFullScreen(true);
}
The first if checks a preference to see if fullscreen is set. the 2nd if sees if another monitor besides the first one was selected. It's 1, so that should be the 2nd monitor. The program loops through all screens and tries to move the program and THEN will go full screen. I know the coordinates are the same but no dice, it still goes full screen on the main screen. Please help.
I don't know if I truly understand your problem, but if you have two screens, why loop through the screens? Why not just use the info associated with the screen in position two/index one of the ObservableList? I am posting a sample app that demos how to display full screen on a second monitor.
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Screen;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication257 extends Application
{
#Override
public void start(Stage primaryStage)
{
ObservableList<Screen> screens = Screen.getScreens();//Get list of Screens
Button btn = new Button();
btn.setText("Full Screen - Screen 1");
btn.setOnAction((ActionEvent event) -> {
Rectangle2D bounds = screens.get(0).getVisualBounds();
primaryStage.setX(bounds.getMinX());
primaryStage.setY(bounds.getMinY());
primaryStage.setFullScreen(true);
//primaryStage.setWidth(bounds.getWidth());
//primaryStage.setHeight(bounds.getHeight());
});
Button btn2 = new Button();
btn2.setText("Full Screen - Screen 2");
btn2.setOnAction((ActionEvent event) -> {
if (screens.size() > 0) {
Rectangle2D bounds = screens.get(1).getVisualBounds();
primaryStage.setX(bounds.getMinX());
primaryStage.setY(bounds.getMinY());
primaryStage.setFullScreen(true);
//primaryStage.setWidth(bounds.getWidth());
//primaryStage.setHeight(bounds.getHeight());
}
});
StackPane root = new StackPane();
root.getChildren().add(new VBox(btn, btn2));
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
I am Trying to build a cinema booker, where I have to select the seats. I was thinking about make placing all my rectangles in an array so i could use it for later, when clicking on a seat it should check if left and right seats are booked. Here the array index should help me. However I cant figure out how to get to this stage. (See picture.)
Take this scenario:
You click on a rectangle (representing a seat). It changes color only it is not Red colored. So Seats[][].checkNeighbourColor or something like that.See picture
package sample;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import java.awt.*;
import java.util.ArrayList;
public class Main extends Application {
private int seats = 12;
private int rows = 8;
private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); //gets screen resolution data
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("");
Group root = new Group();
Scene scene = new Scene(root, screenSize.getWidth()/4, screenSize.getHeight()/3, Color.WHITE);
for (int i = 0; i<= seats; i++)
{
Rectangle r = new Rectangle();
r.setFill(Color.GREEN);
r.setX(scene.getWidth()/5+i*30);
r.setY(scene.getHeight()/5);
r.setWidth(screenSize.getHeight()/80);
r.setHeight(screenSize.getHeight()/80);
root.getChildren().add(r);
for (int q = 0; q<=rows; q++)
{
Rectangle s = new Rectangle();
s.setFill(Color.GREEN);
s.setX(scene.getWidth()/5+i*30);
s.setY(scene.getHeight()/5+q*30);
s.setWidth(screenSize.getHeight()/80);
s.setHeight(screenSize.getHeight()/80);
root.getChildren().add(s);
s.setOnMouseClicked(event ->{
s.setFill(Color.BLACK);
});
}
}
primaryStage.setScene(scene);
primaryStage.show();
}
}
It's not entirely clear to me what you're asking, but can't you just do
private Rectangle[][] rectangles = new Rectangle[seats][rows];
and then just do
rectangles[i][q] = s ;
For your listener you can do
final int row = i ;
final int seat = q ;
s.setOnMouseClicked(event -> {
// check rectangles[row-1][seat] and rectangles[row+1][seat] as needed,
// checking for range of row first
});
Aside: don't mix AWT and JavaFX. Use the Screen API to get the dimension of the physical screen(s) in JavaFX.
Okay I found my mistake. It was a simple ArrayOutOfBound (The statement in my for-loops was wrong), but thank you all for your help :)
This question already has an answer here:
JavaFX: How to connect two Nodes by a Line?
(1 answer)
Closed 7 years ago.
Trying to connect circles together in the picture with a line from the center of the circle to the other circle. The line should be shown will the mouse is being dragged.And when I release the mouse than it should not show any line at all.
This is the code.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.StrokeType;
import javafx.stage.Stage;
public class Projekt extends Application {
#Override
public void start(Stage primaryStage) {
Pane pane = new Pane();
//Inserting Circles
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
Circle c = new Circle(i*60+10,j*60+10,10);
c.setFill(Color.WHITE);
c.setStroke(Color.BLACK);
c.setStrokeWidth(2);
c.setStrokeType(StrokeType.OUTSIDE);
c.setOnMouseDragged((MouseEvent e)->{
Line line = new Line(c.getCenterX(),c.getCenterY(),e.getX(),e.getY());
});
pane.getChildren().add(c);
}
}
Scene scene = new Scene(pane,600,600);
primaryStage.setScene(scene);
primaryStage.setTitle("Hello World!");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
There are several ways to do this.
1-st of all you need to add your line to the pane. Because there is line creation in your code, but nothing adds this line to the pane. And you probably don't want to create new line each time, so just create some line (maybe even static one) and change coords with line.setStartX(x); line.setStartY(y); and line.setEndX(e.getX()); line.setEndY(e.getY()); on each mouse press and mouse drag events.
I think you will not be able to do this with just 1 setOnMouseDragged listener, you have to use at least some other events to set your line visible and invisible.
Here is starter code for you to play with:
public class Main extends Application {
private Line line = new Line();
#Override
public void start(Stage primaryStage) {
Pane pane = new Pane();
line.setVisible(false);
pane.getChildren().add(line);
//Inserting Circles
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
double x = i * 60 + 10;
double y = j * 60 + 10;
Circle c = new Circle(x, y, 10);
c.setFill(Color.WHITE);
c.setStroke(Color.BLACK);
c.setStrokeWidth(2);
c.setStrokeType(StrokeType.OUTSIDE);
c.setOnMousePressed((MouseEvent e) -> {
line.setStartX(x);
line.setStartY(y);
});
c.setOnMouseReleased((MouseEvent e) -> {
line.setVisible(false);
});
c.setOnMouseDragged((MouseEvent e) -> {
line.setEndX(e.getX());
line.setEndY(e.getY());
line.setVisible(true);
});
pane.getChildren().add(c);
}
}