Reputation: 13001
I am trying to capture key press events (page up and down) but there are no key events received at all. Here is the relevant code: Constructor:
private MainLayout() {
imageView = new ImageView();
root = new StackPane();
root.getChildren().add(imageView);
root.setFocusTraversable(true); //no effect
//root.requestFocus(); //also no effect
registerEvents();
}
Both lines regarding the focus don't have an effect. The stack pane is directly added to scene. There are no other nodes than Scene->StackPane->ImageView. I am able to capture key events on the scene, but i need them captured in the stack pane
Here is registerEvents()
, all other events are captured fine!:
private void registerEvents() {
OnScroll onScroll = new OnScroll();
root.setOnScroll(onScroll);
OnResize onResize = new OnResize();
root.heightProperty().addListener(onResize);
root.widthProperty().addListener(onResize);
OnMouseDown onMouseDown = new OnMouseDown();
root.setOnMousePressed(onMouseDown);
root.setOnMouseReleased((event) -> fitImage());
root.setOnDragOver((event) -> dragOver(event));
root.setOnDragDropped((event) -> dropFile(event));
root.setOnKeyPressed((event) -> {
LOG.debug("Key captured.");
if(event.getCode() == KeyCode.PAGE_UP){
imageView.setImage(ip.prev());
event.consume();
} else if(event.getCode() == KeyCode.PAGE_DOWN){
imageView.setImage(ip.next());
event.consume();
}
if(event.isConsumed()){
fitImage();
}
});
I don't see the log out put and a break point is also not caught. So how to catch and handle key events correctly?
Upvotes: 5
Views: 2968
Reputation: 13001
Meanwhile i found the solution thanks to this answer. The trick is to setFocusTraversable(true)
on ImageView (child of stack pane). Here is the working code:
@Inject
private MainLayout(ImageProvider ip) {
this.ip = ip;
imageView = new ImageView();
imageView.setFocusTraversable(true);
imageView.requestFocus();
root = new StackPane();
root.getChildren().add(imageView);
registerEvents();
}
Upvotes: 4
Reputation: 1014
I don't know if this answer will satisfy you, but I would move handling events from this class to the class where you initialize your scene, and attach the events to the scene itself (since StackPane
is, in a way, the scene). I'm guessing that, since the constructor in your code is private, you are instantiating the class via public static method from another class.
public class MainClass extends Application {
private Scene scene = new Scene(MainLayout.getMainLayout());
@Override
public void start(Stage primaryStage) throws Exception {
registerEvents();
primaryStage.setScene(scene);
primaryStage.show();
}
private void registerEvents() {
OnScroll onScroll = new OnScroll();
scene.setOnScroll(onScroll);
OnResize onResize = new OnResize();
scene.heightProperty().addListener(onResize);
scene.widthProperty().addListener(onResize);
OnMouseDown onMouseDown = new OnMouseDown();
scene.setOnMousePressed(onMouseDown);
scene.setOnMouseReleased((event) -> fitImage());
scene.setOnDragOver((event) -> dragOver(event));
scene.setOnDragDropped((event) -> dropFile(event));
scene.setOnKeyPressed((event) -> {
LOG.debug("Key captured.");
if (event.getCode() == KeyCode.PAGE_UP) {
imageView.setImage(ip.prev());
event.consume();
} else if (event.getCode() == KeyCode.PAGE_DOWN) {
imageView.setImage(ip.next());
event.consume();
}
if (event.isConsumed()) {
fitImage();
}
});
}
}
Alternatively, if you want to keep the code for handling events in the MainLayout
class, consider making registerEvents
a public (or package local, depending on your design) method accepting Scene
as a param.
Upvotes: 0