How to write a MouseListener for JavaFX - javafx

I want to write a little game where I shoot from an object to a specific direction on a JavaFX Panel using my mouse position.
I want to turn a Line in the direction where my Mouse is.
Line line = new Line(startPosX, startPosY, mouseDirectionX, mouseDirectionY);
How can I do that?

Add a MOUSE_MOVED event filter like this:
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
Pane root = new Pane();
Line line = new Line( 400,200,400,200);
root.addEventFilter(MouseEvent.MOUSE_MOVED, e -> {
line.setEndX(e.getSceneX());
line.setEndY(e.getSceneY());
});
root.getChildren().add(line);
Scene scene = new Scene(root, 800, 400);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
If you want the line to be limited in length, you'll have to do the proper calculations of course via the angle.

Related

Events for two overlay shapes

My problem:
I have a two overlay shapes, for example, two rectangles: A and B.
When B overlay A rectangle.
I add setOnMouseMoved handlers for both and i see that events handles only by top figure.
Code example:
public class MainExample extends Application {
#Override
public void start(Stage stage) {
stage.setMinWidth(700);
stage.setMaxWidth(700);
stage.setMinHeight(800);
stage.setMaxHeight(800);
StackPane root = new StackPane();
var a = new Rectangle(300, 300, Color.BLUE);
var b = new Rectangle(200, 200);
root.getChildren().addAll(a, b);
b.setOnMouseMoved(mouseEvent -> {
System.out.println("Mouse moved b!");
});
a.setOnMouseMoved(mouseEvent -> System.out.println("Mouse moved a!"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
What i want:
In the area of overlapping figures mouse moved events handles both of figures: A and B.
Thanx everyone for help!
I replace both mouse events to just one in stackpane node . The event checks if mouse coords is inside in both bounds (node a and node b) . When the mouse is in an area that intersetcs both rectangles the event wil thrigger both print statments
public class MainExample extends Application {
#Override
public void start(Stage stage) {
stage.setMinWidth(700);
stage.setMaxWidth(700);
stage.setMinHeight(800);
stage.setMaxHeight(800);
StackPane root = new StackPane();
var a = new Rectangle(300, 300, Color.BLUE);
var b = new Rectangle(200, 200);
root.getChildren().addAll(a, b);
root.setOnMouseMoved(mouseEvent -> {
if(b.getBoundsInParent().contains(mouseEvent.getSceneX(),mouseEvent.getSceneY())){
System.out.println("Mouse moved b!");}
if(a.getBoundsInParent().contains(mouseEvent.getSceneX(),mouseEvent.getSceneY())){
System.out.println("Mouse moved a!");}
});
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}

Javafx TilePane PrefColumns

I am having problems producing the correct number of columns in a TilePane row.
I'm trying just to have ten columns per row. I know I'm missing the obvious. So, I need another pair of eyes.
The setPrefColumns method does not appear to work the way I have it coded.
#SuppressWarnings("unused")
public class Main extends Application {
TilePane tp = new TilePane();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
try {
primaryStage.setResizable(false);
tp.setPrefColumns(10);
setTP();
Scene scene = new Scene(tp,800,600);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public void setTP() {
tp.setVisible(true);
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
for(int row=0; row<11; row++) {
for (int i: numbers ) {
Text t = new Text(String.valueOf(i));
HBox hbox = new HBox();
hbox.getChildren().add(t);
hbox.setStyle("-fx-border-color: red;");
tp.getChildren().add(hbox);
}
}
}
}
Your example TilePane behaves as specified:
Note that prefColumns/prefRows is used only for calculating the preferred size and may not reflect the actual number of rows or columns, which may change as the tilepane is resized and the tiles are wrapped at its actual boundaries.
As root of the scene it is sized to fill the complete width (800 in your context):
Scene scene = new Scene(tp,800,600);
To make it wrap on its prefColumns, you need to add it to a layout that respects its content's prefWidth, f.i. a HBox:
Scene scene = new Scene(new HBox(tp),800,600);

Confusion on why an object wont draw a circle when trying to grab the window size

So, I have a pane being made in one class
#Override //Overridden nerd
public void start(Stage primaryStage) {
//makes a ball
Ball ball = new Ball();
//pause and resume animation
ball.setOnMousePressed(e -> ball.pause());
ball.setOnMouseReleased(e -> ball.play());
//increase/decrease speed
ball.setOnKeyPressed(e-> {
if(e.getCode() == KeyCode.UP) {
ball.increaseSpeed();
}
else if (e.getCode() == KeyCode.DOWN) {
ball.decreaseSpeed();
}
});
//creating a scene and setting its background
Scene scene = new Scene(ball, 500, 500);
primaryStage.setTitle("Random Walker");
primaryStage.setScene(scene);
primaryStage.show();
ball.requestFocus();
}
public static void main(String[] args) {
Application.launch(args);
}
}
and im trying to get the animation to start the ball at the center off the pane, and then bounce off the walls (im not on the bouncing part yet so I know that isnt perfect yet but im trying)
My problem is that when I try to get the ball to draw off of the current size of the window its not drawing anything at all, but will work if I manually put in the default screen size. any insight would be great, as I've been struggling with trying to finding any way to do this for a while, thanks.
public class setup extends Application {
#Override //Overridden nerd
public void start(Stage primaryStage) {
//makes a ball
Ball ball = new Ball();
//pause and resume animation
ball.setOnMousePressed(e -> ball.pause());
ball.setOnMouseReleased(e -> ball.play());
//increase/decrease speed
ball.setOnKeyPressed(e-> {
if(e.getCode() == KeyCode.UP) {
ball.increaseSpeed();
}
else if (e.getCode() == KeyCode.DOWN) {
ball.decreaseSpeed();
}
});
//creating a scene and setting its background
Scene scene = new Scene(ball, 500, 500);
primaryStage.setTitle("Random Walker");
primaryStage.setScene(scene);
primaryStage.show();
ball.requestFocus();
}
public static void main(String[] args) {
Application.launch(args);
}
}

JavaFX button unselect

I'm trying to make a sprite editor using JavaFX using buttons as the pixels. I am able to change the colour of each button on press, but I'm trying to get it so if I click and drag I can paint multiple pixels.
The problem I'm finding is that after clicking and holding onto a button, I am unable to select the new button when I move the mouse over new button to select that one too. If I click and drag re-entering that button I can get the "Paint Dragged Pixel" debug message, but not if I enter a new pixel with the mouse down, which is what I want. Also I can get the pixel button to print "Entered Pixel" when the mouse enters any button, but not for when I click and drag to a new pixel.
I think the problem is that when I click on one pixel I am locked in, and unable to select a new pixel by hovering over a new one. Is there a way to unbind this selection, or is the problem a different one.
Main Application:
public class Main extends Application {
boolean mousePressed = false;
public boolean isMousePressed() {
return mousePressed;
}
#Override
public void start(Stage primaryStage) throws Exception{
BorderPane borderPane = new BorderPane();
primaryStage.setTitle("SpriteSheet");
Group root = new Group();
Scene scene = new Scene(borderPane, 500,200);
scene.setFill(Color.BLACK);
primaryStage.setScene(scene);
GridPane gridPane = new GridPane();
borderPane.setCenter(root);
for(int x = 0; x < 10; x++)
{
for(int y = 0; y < 10; y++) {
PixelButton button = new PixelButton();
button.setParentMain(this);
button.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
mousePressed = true;
System.out.println("mouseDown");
}
});
button.setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
mousePressed = false;
System.out.println("mouseUp");
}
});
gridPane.add(button, x, y);
}
}
root.getChildren().add(gridPane);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The class for the PixelButton.
public class PixelButton extends Button {
Main parentMain;
public void setParentMain(Main parent) {
parentMain = parent;
}
public PixelButton() {
this.setMinSize(10, 10);
this.setPrefSize(10, 10);
this.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
}
});
this.setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("Entered Pixel");
if(parentMain.isMousePressed()){
System.out.println("Paint Dragged Pixel");
}
}
});
}
}
Thank you in advance.
Ok so I have been thinking about this one for a bit and have finally come up with a solution I simplified my solution a bit and used rectangles instead of buttons but you can transfer most of the code to the buttons as well so to start with this is not the exact functionality you were looking for but as close as I could get basically I fire an event on mouse press that releases the mouse click and as long as that event is not coming from the rectangle then dont flip the painting boolean paint and so you basically click to enter a "Paint Mode" and click again to get out of coloring tiles
public class Main extends Application {
private boolean mousePressed;
#Override
public void start(Stage primaryStage) throws Exception{
BorderPane borderPane = new BorderPane();
primaryStage.setTitle("SpriteSheet");
Group root = new Group();
Scene scene = new Scene(borderPane, 500,200);
// scene.setFill(Color.BLACK);
primaryStage.setScene(scene);
GridPane gridPane = new GridPane();
borderPane.setCenter(root);
for(int x = 0; x < 10; x++) {
for(int y = 0; y < 10; y++) {
Rectangle rectangle = new Rectangle(10, 10);
rectangle.setOnMousePressed(event -> {
mousePressed = true;
System.out.println("mouseDown");
rectangle.fireEvent(new MouseEvent(MouseEvent.MOUSE_RELEASED,
rectangle.getLayoutX(), rectangle.getLayoutY(), rectangle.getLayoutX(), rectangle.getLayoutY(),
MouseButton.PRIMARY, 1,
false, false, false, false,
false, false, false, false,
false, false, null));
});
rectangle.setOnMouseReleased(event -> {
System.out.println(event.getSource());
if(!event.getSource().toString().equals("Rectangle[x=0.0, y=0.0, width=10.0, height=10.0, fill=0x000000ff]")) {
mousePressed = false;
System.out.println("mouseUp");
}
});
rectangle.setOnMouseMoved(event -> {
if(mousePressed) {
rectangle.setFill(Color.BLUE);
}
});
gridPane.add(rectangle, x, y);
}
}
root.getChildren().add(gridPane);
primaryStage.show();
}
public static void main(String[] args) { launch(args); }
}

How can I assign an EventListener to a Path in javafx?

I have this piece of code which doesn't work correctly.
I want to set a listener for when a user clicks inside the square, yet
neither the pop-up nor the message "clicked" are displayed when I click
inside the square.
What am I missing?
This method is inside the Coords class.
public static void drawMyShape(final GraphicsContext ctx) {
Path path = new Path();
MoveTo mT = new MoveTo();
LineTo lT[] = new LineTo[4];
mT.setX(200.0);
mT.setY(200.0);
lT[0] = new LineTo(400.0, 200.0);
lT[1] = new LineTo(400.0, 400.0);
lT[2] = new LineTo(200.0, 400.0);
lT[3] = new LineTo(200.0, 200.0);
path.setStroke(Color.BEIGE);
path.getElements().addAll(mT, lT[0], lT[1], lT[2], lT[3]);
path.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
final Stage dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(Main.prim_stage);
VBox box = new VBox(20);
box.getChildren().add(new Text("Hey"));
Scene s = new Scene(box, 300, 200);
dialog.setScene(s);
dialog.show();
System.out.println("Clicked");
}
});
ctx.setLineWidth(4.0);
ctx.beginPath();
ctx.moveTo(mT.getX(), mT.getY());
for (int i = 0; i < lT.length; i++) {
ctx.lineTo(lT[i].getX(), lT[i].getY());
}
ctx.closePath();
ctx.stroke();
}
EDITED ON SUGGESTION by users.
So his is the main program:
public class Main extends Application {
public static Pane root;
private static Canvas main_canvas;
private static GraphicsContext ctx;
private static Rectangle2D bounds;
private static Scene scene;
public static Stage prim_stage;
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Switzerland Advertising");
initElements(primaryStage);
Coords.drawMyShape(ctx);
primaryStage.show();
System.out.println("Launched");
}
public static void main(String[] args) {
launch(args);
}
}
Everything is instanciated inside the following function, which works correctly and displays a full screen application with a canvas and a square drawn into it (image at the bottom).
private void initElements(final Stage primaryStage) {
prim_stage = primaryStage;
// ----------------------------------------
bounds = Screen.getPrimary().getVisualBounds();
double w = bounds.getWidth();
double h = bounds.getHeight();
// ----------------------------------------
// init elements of scene
root = new Pane();
main_canvas = new Canvas(w, h);
// ----------------------------------------
// init scene elements
scene = new Scene(root, w, h);
primaryStage.setX(bounds.getMinX());
primaryStage.setY(bounds.getMinY());
primaryStage.setWidth(w);
primaryStage.setHeight(h);
primaryStage.setScene(scene);
// ----------------------------------------
ctx = main_canvas.getGraphicsContext2D();
// set elements in main pane
root.getChildren().add(main_canvas);
// ----------------------------------------
}
So how can I make the pop-up window appear whenever I click inside the region drawn on the canvas?
This is the program
Your path is just a local variabl within your method. It has to be attached to the scene graph in order to get events. But when you attach it to the scene graph, drawing the same path on a canvas also does not make much sense.

Resources