简体   繁体   中英

Javafx KeyEvent and MouseEvent

I am trying to learn javafx. I did most of the code but I am having trouble with the start method.

What I wanted to do was add spots to the screen by clicking on it. And if I press either 1 or 0 future spots that will be added will change to some different color. Therefore, I know that I must use setOnMouseClicked and setOnKeyPressed methods but there isn't much on the internet on it.

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;


public class Spots extends Application {

    public static final int SIZE = 500;    
    public static final int SPOT_RADIUS = 20;    
    private LinkedList<Spot> spotList;    
    private Color color;

    public static void main(String...args) {
        launch(args);
    }

    public void start(Stage stage) {

        stage.setTitle("Spots");    
        dotList = new SinglyLinkedList<>();        
        Group root = new Group();
        Scene scene = new Scene(root, 500, 500, Color.BLACK);
        Spot r;

        // ...    

        stage.show(); 
    }

    private class Spot extends Circle {

        public Spot(double xPos, double yPos) {
            super(xPos, yPos, SPOT_RADIUS);
            setFill(color);
        }

        public boolean contains(double xPos, double yPos) {
            double dx = xPos - getCenterX();
            double dy = yPos - getCenterY();
            double distance = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
            return distance <= SPOT_RADIUS;
        }        
    }
}

The reason the circle is not accepting is that it is not focused. For nodes to respond to key events they should be focusTraversable . You can do that by calling setFocusTraversable(true) on the node. I edited your start() method and here is the code I ended up with.

public void start(Stage primaryStage) throws Exception {

    Pane pane = new Pane();
    final Scene scene = new Scene(pane, 500, 500);
    final Circle circle = new Circle(250, 250, 20);
    circle.setFill(Color.WHITE);
   circle.setStroke(Color.BLACK);
    pane.getChildren().add(circle);
     circle.setFocusTraversable(true);
    circle.setOnKeyPressed(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent e) {
            if ((e.getCode() == KeyCode.UP) && (circle.getCenterY() >= 5)) {
                circle.setCenterY(circle.getCenterY() - 5);
            }

            else if ((e.getCode() == KeyCode.DOWN && (circle.getCenterY() <= scene.getHeight() - 5))) {
                circle.setCenterY(circle.getCenterY() + 5);
            }
            else if ((e.getCode() == KeyCode.RIGHT) && (circle.getCenterX() <= scene.getWidth() - 5)) {
                circle.setCenterX(circle.getCenterX() + 5);
            }
            else if ((e.getCode() == KeyCode.LEFT && (circle.getCenterX() >= 5))) {

                circle.setCenterX(circle.getCenterX()-5);
            }
        }
    });

  //creates new spots by clicking anywhere on the pane
    pane.setOnMouseClicked(new EventHandler<MouseEvent>() {  
      public void handle(MouseEvent event) {
            double newX = event.getX(); //getting the x-coordinate of the clicked area
            double newY = event.getY(); //getting the y-coordinate of the clicked area

            Circle newSpot = new Circle(newX, newY,20);
            newSpot.setFill(Color.WHITE);
            newSpot.setStroke(Color.BLACK);
            pane.getChildren().add(newSpot);

        }
    });

    primaryStage.setTitle("Move the circle");
    primaryStage.setScene(scene);
    primaryStage.show();
}

Also take look at the answers for the following links:

Solution Approach

You can monitor the scene for key typed events and switch the color mode based on that. You can place an mouse event handler on your scene root pane and add a circle (of the appropriate color for the prevailing color mode) to the scene when the user clicks anywhere in the pane.

Sample Code

斑点

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

// Java 8+ code.
public class Spots extends Application {

    private static final int SIZE = 500;
    private static final int SPOT_RADIUS = 20;

    private Color color = Color.BLUE;

    public void start(Stage stage) {
        Pane root = new Pane();

        root.setOnMouseClicked(event ->
                root.getChildren().add(
                        new Spot(
                                event.getX(),
                                event.getY(),
                                color
                        )
                )
        );

        Scene scene = new Scene(root, SIZE, SIZE, Color.BLACK);
        scene.setOnKeyTyped(event -> {
            switch (event.getCharacter()) {
                case "0":
                    color = Color.BLUE;
                    break;
                case "1":
                    color = Color.RED;
                    break;
            }
        });

        stage.setScene(scene);
        stage.show();
    }

    private class Spot extends Circle {
        public Spot(double xPos, double yPos, Color color) {
            super(xPos, yPos, SPOT_RADIUS);
            setFill(color);
        }
    }

    public static void main(String... args) {
        launch(args);
    }
}

Further Info

Generally, you'd use setOnAction as shown in the Oracle tutorials .

Example:

    btn.setOnAction(new EventHandler<ActionEvent>() {

        public void handle(ActionEvent event) {
            System.out.println("Hello World");
        }
    });

If the particular Node you're trying to use does not have a clickHandler method, try doing something like this (on Group for example):

    group.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            System.out.println("Hello!");
        }
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM