Welcome to the CSC Q&A, on our server named in honor of Ada Lovelace. Write great code! Get help and give help!
It is our choices... that show what we truly are, far more than our abilities.

Categories

+9 votes

In the initialize method of MainViewController, I put in the line drawingCanvas.setOnKeyPressed(keyEvent -> keyPressed(keyEvent)); which calls the method keyPress, which checks whether the key pressed was the delete key and deletes the figure if so. The problem is that apparently the canvas is not recognizing the key presses at all; I added a print statement to the keyPress method, and it never prints. Is there a different object that I should be asking to listen for the key press, or why does this one not work?

asked in CSC 305 Fall 2024 by (4.5k points)

1 Answer

+7 votes

This is a great question! (By which, I mean Amy's question, not mine!)

I wrote this sample exam problem before trying it myself, thinking that it would be a straightforward thing to transfer over some knowledge from your team projects, where you are using keyboard input for paddle or straight keys.

However, it's not quite so straightforward.

In JavaFX it turns out that a canvas object doesn't have keyboard "focus" by default, and can't receive the key events.

The easiest way to remedy this is probably to do the following commands:

drawingCanvas.setFocusTraversable(true);
drawingCanvas.addEventFilter(MouseEvent.ANY, (e) -> drawingCanvas.requestFocus());
drawingCanvas.setOnKeyPressed(e -> System.out.println(e));

This: 1) allows the canvas to get keyboard focus, and 2) actually puts the keyboard focus on the canvas any time that ANY mouse event happens (clicking, or even moving the mouse cursor over the canvas). The last line just prints out the key event, but should probably be replaced with something like:

drawingCanvas.setOnKeyPressed(e -> deleteAction());

where you implement a deleteAction() method in your controller.

Note: There are other ways to work around this as well, such as setting the onKeyPressed on the Scene object, instead instead of the canvas, but it's a bit tricky to access the Scene during the initialize method, because the components haven't been added to the Scene yet. Thus, you can do something like:

Platform.runLater(() -> drawingCanvas.getScene().setOnKeyPressed(e -> System.out.println(e)));

which schedules the key event handler to get set on the Scene after the root pane has been added to the scene.

In any case, I apologize that this was a bit trickier than expected. If something similar comes up on the real exam, at least you can come back to this Q&A question!

answered by (4.9k points)
edited by
...