I trying to build map which consist of regions(states) and when mouse entered to some region, I need handle it. Have many png images which represent each region separately. I blend my images and got what I want, but I can't handle some region.
For instance:
It's a first region img
This is a second region img
As result I got:
Code:
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("view/MapView.fxml"));
Pane root = loader.load();
primaryStage.setTitle("Map");
primaryStage.setScene(new Scene(root, 700, 700));
primaryStage.show();
//First region
File file = new File("src/res/img/region1.png");
Canvas canvas = new Canvas(700, 700);
canvas.addEventHandler(MouseEvent.MOUSE_ENTERED_TARGET, event -> System.out.println("Region 1"));
GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
graphicsContext.drawImage(new Image(file.toURI().toString()), 0, 0);
root.getChildren().add(canvas);
//Second region
file = new File("src/res/img/region2.png");
canvas = new Canvas(700, 700);
canvas.addEventHandler(MouseEvent.MOUSE_ENTERED_TARGET, event -> System.out.println("Region 2"));
graphicsContext = canvas.getGraphicsContext2D();
graphicsContext.drawImage(new Image(file.toURI().toString()), 0, 0);
root.getChildren().add(canvas);
}
In console I got always "Region 2".
Please give me tips for research. Thanks in advance!
You can use an ImageView and setPickOnBounds for that.
Example code:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class LayersWithMouseEvents extends Application {
#Override
public void start(Stage primaryStage) {
// root
StackPane root = new StackPane();
// create layers
Pane region1Layer = new Pane();
Pane region2Layer = new Pane();
// add layers
root.getChildren().addAll(region1Layer, region2Layer);
// load images
ImageView region1ImageView = new ImageView( new Image( getClass().getResource("region1.png").toExternalForm()));
ImageView region2ImageView = new ImageView( new Image( getClass().getResource("region2.png").toExternalForm()));
// add images
region1Layer.getChildren().add(region1ImageView);
region2Layer.getChildren().add(region2ImageView);
// mouse handler
region1Layer.setOnMousePressed(e -> System.out.println("Region 1: " + e));
region2Layer.setOnMousePressed(e -> System.out.println("Region 2: " + e));
// this is the magic that allows you to click on the separate layers, but ONLY(!) as long as the layer is transparent
region1Layer.setPickOnBounds(false);
region2Layer.setPickOnBounds(false);
primaryStage.setScene(new Scene(root, 800, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
In the future please create an MCVE with focus on complete. Nobody wants to waste their time in order to make your incomplete example work.
To my opinion using a canvas here is not the right approach. If you would define your regions as polygons and add them to the scene graph you can attach a listener to each of these polygons and then react accordingly if the mouse is over some region. Maybe this is also possible with image views but I have never tried wether a transparent region of an image is also mouse transparent which seems to be necessary in that case. For a program of mine I used polygons and it works nicely.
The image data can be used to determine the color of the pixels under the mouse cursor. If the pixel is not fully transparent, then the cursor is on that region.
To retrieve this information you need to use a listener for the mouse moved event. For simplicity you can use a property with a listener attached to trigger the region enter/leave events:
The following example assumes you keep references to the images used for the regions named image1 and image2:
PixelReader reader1 = image1.getPixelReader();
PixelReader reader2 = image2.getPixelReader();
SimpleIntegerProperty region = new SimpleIntegerProperty(-1);
region.addListener((observable, oldValue, newValue) -> {
if (newValue.intValue() < 0) {
System.out.println("region left");
} else {
System.out.println("Region " + (newValue.intValue() + 1));
}
});
canvas.setOnMouseMoved(event -> {
int x = (int) event.getX();
int y = (int) event.getY();
if (x < image1.getWidth() && y < image1.getHeight() && reader1.getColor(x, y).getOpacity() != 0) {
region.set(0);
} else if (x < image2.getWidth() && y < image2.getHeight() && reader2.getColor(x, y).getOpacity() != 0) {
region.set(1);
} else {
region.set(-1);
}
});
Also there is no need to create multiple Canvas to paint the images.
Related
I am trying to develop a tool with JavaFX that has multiple viewports and I think the best way to do that is through the use of SubScenes. One requirement I have is the ability to know where on a given plane in the scene corresponds to the pixel clicked by the mouse. I thought that I could use the Node.localToScreen() and Node.screenToLocal() functions to do this, however when adding a SubScene I get different values, despite nothing else changing.
Below is an example, where running the code with withSubScene = false, the console shows:
Point2D [x = 996.0, y = 514.8333400189878]
Point2D [x = 117.98005476276654, y = 514.8333400189878]
And running with withSubScene = true, the console shows:
Point2D [x = 997.0, y = 529.3333400189878]
Point2D [x = 64.91937872905163, y = 529.3333400189878]
Why would these values be different, when the camera is in the same location and looking at the same object?
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class ScreenToLocalTest extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
// Change this variable to swap to adding a SubScene
boolean withSubScene = false;
// Set the stage to be the same size each time
primaryStage.setWidth(1000);
primaryStage.setHeight(500);
Group root = new Group();
Scene rootScene = new Scene(root);
// Create out camera
Camera camera = new PerspectiveCamera(true);
camera.setTranslateZ(-1000);
camera.setNearClip(1);
camera.setFarClip(10000);
Group groupToAddRectangle;
if(withSubScene) {
Group sceneRoot = new Group();
SubScene subScene = new SubScene(sceneRoot, primaryStage.getWidth(), primaryStage.getHeight());
root.getChildren().add(subScene);
subScene.setCamera(camera);
groupToAddRectangle = sceneRoot;
} else {
rootScene.setCamera(camera);
groupToAddRectangle = root;
}
Rectangle rectangle = new Rectangle(1000, 300, Color.ALICEBLUE);
groupToAddRectangle.getChildren().add(rectangle);
rectangle.setTranslateZ(1);
root.setOnMouseMoved(event-> {
System.out.println(rectangle.screenToLocal(event.getScreenX(), event.getScreenY()));
});
primaryStage.setScene(rootScene);
primaryStage.show();
System.out.println(rectangle.localToScreen(0, 0));
rectangle.translateXProperty().set(-1000);
System.out.println(rectangle.localToScreen(0, 0));
}
public static void main(String[] args) {
launch(args);
}
}
I have a program in which it displays 3 random hieroglyphic images on the screen. I have added a "Refresh" button in order to refresh the hieroglyphic images. When I click the button, the images refresh and randomize properly. After the button has been clicked for the first time however, it disappears. I am almost certain it has something to do with my pane.getChildren().clear(); line, but I cant seem to figure it out. Any tips or advice?
If I have posted incorrectly or without using proper guidelines, I apologize. This is one of my first posts.
Here is my code:
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.control.Button;
import javafx.geometry.Pos;
import javafx.scene.layout.HBox;
public class Lab6a extends Application {
#Override
public void start(Stage myStage) {
//Create an HBox layout.
HBox hBox1 = new HBox();
//Set alignment.
hBox1.setAlignment(Pos.CENTER);
getRandomHieroglyphic(hBox1);
//Create a Refresh button.
Button refresh = new Button("Refresh");
refresh.setOnAction(e -> getRandomHieroglyphic(hBox1));
hBox1.getChildren().add(refresh);
//Set the title for the second window.
myStage.setTitle("Random Hieroglyphics with Refresh");
//Create a scene for the window.
Scene myScene = new Scene(hBox1, 400, 400);
//Place the scene in the second window.
myStage.setScene(myScene);
//Show the stage.
myStage.show();
}
public void getRandomHieroglyphic(HBox pane) {
pane.getChildren().clear();
//Create random generators to get a random image
int randomInt1 = (int) (Math.random() * 9) + 1;
int randomInt2 = (int) (Math.random() * 9) + 1;
int randomInt3 = (int) (Math.random() * 9) + 1;
//Create paths for the images to be called
String path1 = "Image/Hieroglyphics/h" + randomInt1 + ".png";
String path2 = "Image/Hieroglyphics/h" + randomInt2 + ".png";
String path3 = "Image/Hieroglyphics/h" + randomInt3 + ".png";
//Add the images into the pane
pane.getChildren().add(new ImageView (path1));
pane.getChildren().add(new ImageView (path2));
pane.getChildren().add(new ImageView (path3));
}
public static void main(String[] args) {
launch(args);
}
}
clear() removes all children from the HBox including the Button.
You've got 3 ImageViews and want to keep the number of ImageViews constant. This means you should not replace them, but replace the images they contain instead. Furthermore you should avoid reloading the images and load all 9 images at the start:
public class Lab6a extends Application {
private Image[] images;
private final Random random = new Random();
#Override
public void start(Stage myStage) {
// load all hieroglyphs
images = new Image[9];
for (int i = 0; i < images.length; i++) {
images[i] = new Image("Image/Hieroglyphics/h" + (i+1) + ".png");
}
// store all imageviews in array
final ImageView[] imageViews = Stream.generate(ImageView::new).limit(3).toArray(ImageView[]::new);
// set initial images
getRandomHieroglyphic(imageViews);
...
hBox1.getChildren().add(refresh);
for (ImageView iv : imageViews) {
hBox1.getChildren().add(iv);
}
...
refresh.setOnAction(e -> getRandomHieroglyphic(imageViews));
...
}
public void getRandomHieroglyphic(ImageView[] imageViews) {
for (ImageView iv : imageViews) {
iv.setImage(images[random.nextInt(images.length)]);
}
}
You're right. You Hbox has 4 cildren initially, 3 images and the button. you should add the button too in the getRandomHieroglyphic() method.
But the better way was separate the button from the images. Best is this done by Adding a BorderPane to the Scene, and put the HBox with the images only in the center and the button in the bottom area.
#Override
public void start(Stage myStage) {
HBox hBox1 = new HBox();
hBox1.setAlignment(Pos.CENTER);
getRandomHieroglyphic(hBox1);
Button refresh = new Button("Refresh");
refresh.setOnAction(e -> getRandomHieroglyphic(hBox1));
BorderPane borderPane = new BorderPane();
borderPane.getBottom().add(refresh);
myStage.setTitle("Random Hieroglyphics with Refresh");
Scene myScene = new Scene(borderPane, 400, 400);
I am creating slot machine application with javafx. Desired behavior: separated pictures have to appear in pane as real slot machine drum during animation (pictures of cherry, lemon, number sever and etc should look like one whole peace for user) like showing on picture.
slot machine
My problem is I can't put together separate images to scrolling in slot machine window seamless.
I have made a lot of search about this problem but didn't find any working solutions. I have tried to add all images in ArrayList and then set them as node to TranslateTransition reference during animation process. But initial image stack in windows.
import javafx.animation.Interpolator;
import javafx.animation.ParallelTransition;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TestClass extends Application {
private BorderPane borderPane = new BorderPane();
private GridPane gridPane = new GridPane();
#Override
public void start(Stage primaryStage) throws Exception {
ImageView image1 = new ImageView(createImage(Color.RED));
ImageView image2 = new ImageView(createImage(Color.GREEN));
ImageView image3 = new ImageView(createImage(Color.BLUE));
gridPane.setLayoutX(50);
gridPane.setLayoutY(50);
gridPane.setPadding(new Insets(5, 5, 5, 5));
gridPane.setAlignment(Pos.CENTER);
gridPane.setVgap(5);
gridPane.add(image1, 0, 0);
gridPane.add(image2, 1, 0);
gridPane.add(image3, 2, 0);
gridPane.setMaxWidth(image1.getFitWidth() * 3);
gridPane.setMaxHeight(image1.getFitHeight());
Rectangle clip = new Rectangle(732, 230);
clip.setLayoutX(30);
clip.setLayoutY(10);
clip.setStroke(Color.BLACK);
// clip.setFill(null);
gridPane.setClip(clip);
borderPane.setCenter(gridPane);
Scene scene = new Scene(borderPane, 900, 500);
primaryStage.setScene(scene);
primaryStage.setTitle("SlotMachine");
primaryStage.show();
ImageView[] images = { image1, image2, image3 };
TranslateTransition t1 = new TranslateTransition();
for (ImageView i : images) {
t1.setDuration(Duration.millis(2000));
t1.setNode(i);
t1.setFromX(image1.getX());
t1.setFromY(image1.getY() - gridPane.getHeight());
t1.setToX(image1.getX());
t1.setToY(image1.getY() - image1.getFitHeight() / 2 + gridPane.getHeight());
t1.setCycleCount(2);
t1.setAutoReverse(false);
t1.setInterpolator(Interpolator.LINEAR);
}
TranslateTransition t2 = new TranslateTransition();
for (ImageView i : images) {
t2.setDuration(Duration.millis(2000));
t2.setNode(i);
t2.setFromX(image2.getX());
t2.setFromY(image2.getY() - gridPane.getHeight());
t2.setToX(image2.getX());
t2.setToY(image2.getY() - image2.getFitHeight() / 2 + gridPane.getHeight());
t2.setCycleCount(2);
t2.setAutoReverse(false);
t2.setInterpolator(Interpolator.LINEAR);
}
TranslateTransition t3 = new TranslateTransition();
for (ImageView i : images) {
t3.setDuration(Duration.millis(2000));
t3.setNode(i);
t3.setFromX(image3.getX());
t3.setFromY(image3.getY() - gridPane.getHeight());
t3.setToX(image3.getX());
t3.setToY(image3.getY() - image3.getFitHeight() / 2 + gridPane.getHeight());
t3.setCycleCount(2);
t3.setAutoReverse(false);
t3.setInterpolator(Interpolator.LINEAR);
}
ParallelTransition pt = new ParallelTransition(t2, t3, t1);
pt.play();
}
private final Image createImage(Color color) {
Rectangle rect = new Rectangle(32, 32);
rect.setFill(color);
return rect.snapshot(null, null);
}
public static void main(String[] args) {
launch(args);
}
}
Please help. Thank you in advance
From what I can tell, it doesn't look like you are using Model/View/Controller architecture; using this architecture is the easiest way (in my opinion) to implement a gui like this. In your case, you could model your logic from the following psuedo-code:
In Controller:
//changes x or y coordinate (depending on direction of movement) of top left corner
//the controller should change the values of x or y that are stored in your model
moveImageMethod(image);
In View:
//Number of ms between timer events, play with this number to make it smooth
private static final int TIMER_INTERVAL = 1000/30;
//constructor
public View(){
<your other stuff, event handlers, etc.>
this.timer = new Timer(TIMER_INTERVAL, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
handleTimerTick();
}
});
}
// Start the animation timer.
public void startTimer() {
timer.start();
}
protected void handleTimerTick(){
controller.moveImageMethod(image);
<other stuff you might need/want>
repaint();
}
<your graphics methods>
Let's say I've got a StackPane which has a BackgroundImage as background and another StackPane (or another component, if neccessary) as a child. The child covers only a part of the parent StackPane.
I'd like to know how to apply a GaussianBlur just to the area the child covers, so that the BackgroundImageis blurry in this area.
The size of the child changes when the parent is resized. It would be perfect to get a solution that will resize just in time, too.
If you want to do it manually, you can use the snapshot function to create a snapshot image, blur it and apply it to the child every time the parent is resized.
However, invoking snapshot all the time will cause performance loss. I rather suggest you create 2 images, one normal and one blurred, and display a viewport of the blurred one.
Here's a more "complex" example with a circle where the viewport isn't sufficient. The clip method is used in this case:
public class Lens extends Application {
Image image = new Image( "http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/800px-Siberischer_tiger_de_edit02.jpg");
CirclePane circlePane;
#Override
public void start(Stage primaryStage) {
ImageView normalImageView = new ImageView( image);
ImageView blurredImageView = new ImageView( image);
blurredImageView.setEffect(new GaussianBlur( 40));
Group root = new Group();
root.getChildren().addAll( normalImageView);
Scene scene = new Scene( root, 1024, 768);
primaryStage.setScene( scene);
primaryStage.show();
// pane with clipped area
circlePane = new CirclePane( blurredImageView);
makeDraggable( circlePane);
root.getChildren().addAll( circlePane);
}
public static void main(String[] args) {
launch(args);
}
private class CirclePane extends Pane {
ImageView blurredImageView;
ImageView clippedView = new ImageView();
public CirclePane( ImageView blurredImageView) {
this.blurredImageView = blurredImageView;
// new imageview
update();
getChildren().addAll( clippedView);
}
public void update() {
// create circle
Circle circle = new Circle( 200);
circle.relocate( getLayoutX(), getLayoutY());
// clip image by circle
blurredImageView.setClip(circle);
// non-clip area should be transparent
SnapshotParameters parameters = new SnapshotParameters();
parameters.setFill(Color.TRANSPARENT);
// new image from clipped image
WritableImage wim = null;
wim = blurredImageView.snapshot(parameters, wim);
clippedView.setImage( wim);
}
}
// make node draggable
class DragContext {
double x;
double y;
}
public void makeDraggable( Node node) {
final DragContext dragDelta = new DragContext();
node.setOnMousePressed(mouseEvent -> {
dragDelta.x = node.getBoundsInParent().getMinX() - mouseEvent.getScreenX();
dragDelta.y = node.getBoundsInParent().getMinY() - mouseEvent.getScreenY();
});
node.setOnMouseDragged(mouseEvent -> {
node.relocate( mouseEvent.getScreenX() + dragDelta.x, mouseEvent.getScreenY() + dragDelta.y);
circlePane.update();
});
}
}
Just click on the circle and drag it around.
I would like to resize the below created shape. but cannot get it.
The project is to create a transparent rectangle to show only a part of the desktop, and hide the rest. The transparent zone is the result of a substraction, and I need to make it resizable by the user.
I tryed several ways, such as adapting from this : https://gist.github.com/jewelsea/1441960
But couldn't get it.
Here is my code :
#Override
public void start(Stage stage) {
Group group = new Group();
Rectangle rect = new Rectangle(0, 0, 350, 300);
Rectangle clip = new Rectangle(20, 20, 200, 200);
clip.setArcHeight(15);
clip.setArcWidth(15);
Shape shape = Shape.subtract(rect, clip);
shape.setFill(Color.GRAY);
group.getChildren().add(shape);
Scene scene = new Scene(group);
scene.setFill(Color.TRANSPARENT);
stage.initStyle(StageStyle.TRANSPARENT);
stage.setScene(scene);
stage.show();
}
Any link or help would be appreciated.
If you create a Shape by Shape.subtract(...), you don't have any mechanism to change the properties of it afterwards (in the sense of changing the bounds of the shapes that were used to create it). You would have to remove the shape from its parent, recompute the rect and clip, recompute the shape, and add the new shape back into the scene.
It might be better to use a Path here so that you can manipulate the coordinates without creating a new shape every time. Traverse one way (say clockwise) around the outside (filled portion), and then the other way (anti-clockwise) around the inner (transparent portion). The resulting shape will be the same as a subtraction of the inner portion from the outer portion. The initial setup will potentially require considerably more code, but you can then manipulate the coordinates as you need to.
I'm not sure exactly what functionality you were looking for, but the following allows you to drag the inner portion around by clicking and dragging on it, and allows you to move the whole window by clicking and dragging on the outer portion. It should be enough for you to figure out what you need. I didn't include the nice rounded corners you had in your example, but you can fairly easily implement those using ArcTo path elements.
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ObservableDoubleValue;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.ClosePath;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.PathElement;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class TransparentRectangle extends Application {
#Override
public void start(Stage stage) {
Pane root = new Pane();
PathElement start = new MoveTo(0, 0);
PathElement outerTopRight = createBoundLineTo(root.widthProperty(), 0);
PathElement outerBottomRight = createBoundLineTo(root.widthProperty(), root.heightProperty());
PathElement outerBottomLeft = createBoundLineTo(0, root.heightProperty());
PathElement outerTopLeft = new LineTo(0, 0);
DoubleProperty innerLeft = new SimpleDoubleProperty(20);
DoubleProperty innerTop = new SimpleDoubleProperty(20);
DoubleBinding innerRight = innerLeft.add(180);
DoubleBinding innerBottom = innerTop.add(180);
PathElement innerTopLeft = createBoundLineTo(innerLeft, innerTop);
PathElement innerTopRight = createBoundLineTo(innerRight, innerTop);
PathElement innerBottomRight = createBoundLineTo(innerRight, innerBottom);
PathElement innerBottomLeft = createBoundLineTo(innerLeft, innerBottom);
Path path = new Path(
start, outerTopRight,
outerBottomRight, outerBottomLeft,
outerTopLeft,
innerTopLeft, innerBottomLeft,
innerBottomRight, innerTopRight,
innerTopLeft, new ClosePath()
);
path.setFill(Color.GRAY);
path.setStroke(Color.TRANSPARENT);
root.getChildren().add(path);
class Wrapper<T> { T value ; }
Wrapper<Point2D> mouseLocation = new Wrapper<>();
// Drag on gray portion of path - move entire window:
path.setOnDragDetected(event -> {
mouseLocation.value = new Point2D(event.getScreenX(), event.getScreenY());
});
path.setOnMouseDragged(event -> {
if (mouseLocation.value != null) {
stage.setX(stage.getX() + event.getScreenX() - mouseLocation.value.getX());
stage.setY(stage.getY() + event.getScreenY() - mouseLocation.value.getY());
mouseLocation.value = new Point2D(event.getScreenX(), event.getScreenY());
}
});
path.setOnMouseReleased(event -> mouseLocation.value = null);
// Drag on scene (i.e not on path, i.e. on transparent part) - move transparent part
root.setOnDragDetected(event -> {
mouseLocation.value = new Point2D(event.getScreenX(), event.getScreenY());
});
root.setOnMouseDragged(event -> {
if (mouseLocation.value != null) {
innerLeft.set(innerLeft.get() + event.getScreenX() - mouseLocation.value.getX());
innerTop.set(innerTop.get() + event.getScreenY() - mouseLocation.value.getY());
mouseLocation.value = new Point2D(event.getScreenX(), event.getScreenY());
}
});
root.setOnMouseReleased(event -> mouseLocation.value = null);
// No close button on a transparent window, so exit on double click:
root.setOnMouseClicked(event -> {
if (event.getClickCount() == 2) Platform.exit();
event.consume();
});
Scene scene = new Scene(root, 800, 600);
scene.setFill(Color.TRANSPARENT);
stage.initStyle(StageStyle.TRANSPARENT);
stage.setScene(scene);
stage.show();
}
private PathElement createBoundLineTo(ObservableDoubleValue x, ObservableDoubleValue y) {
LineTo lineTo = new LineTo();
lineTo.xProperty().bind(x);
lineTo.yProperty().bind(y);
return lineTo ;
}
private PathElement createBoundLineTo(double fixedX, ObservableDoubleValue y) {
LineTo lineTo = new LineTo();
lineTo.setX(fixedX);
lineTo.yProperty().bind(y);
return lineTo ;
}
private PathElement createBoundLineTo(ObservableDoubleValue x, double fixedY) {
LineTo lineTo = new LineTo();
lineTo.setY(fixedY);
lineTo.xProperty().bind(x);
return lineTo ;
}
public static void main(String[] args) {
launch(args);
}
}