0

For education purposes I am trying to add hotkeys to my javafx application. Using my sample code, I am unable to access my label via hotkey. Using a button I can call the very same method updating my label succesfully.

The View:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="62.0" prefWidth="91.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fx.probleme.SampleViewController">
   <children>
      <Label id="label" fx:id="label" layoutX="14.0" layoutY="45.0" text="Label" />
      <Button layoutX="20.0" layoutY="14.0" mnemonicParsing="false" onAction="#updateText" text="Button" />
   </children>
</AnchorPane>

And the controller:

package fx.probleme;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;

public class SampleViewController extends Application {

    @FXML
    Label label;

    @FXML
    void updateText() {
        label.setText(label.getText() + "+");
    }

    @Override
    public void start(Stage stage) throws Exception {
        Parent parent = FXMLLoader.load(this.getClass().getResource("SampleView.fxml"));
        Scene scene = new Scene(parent);
        scene.setOnKeyPressed((final KeyEvent keyEvent) -> {
            if (keyEvent.getCode() == KeyCode.NUMPAD0) {
                updateText();
            }
        });
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
midorlo
  • 33
  • 5

1 Answers1

0

You get NullPointerException, because at that stage the Label is not initialized, the initialization is done in the initialize. First of all you have mixed your main class with your controller class, you may want to separate them, setting a controller that implements Initializable, after that in the initialize method you can call any method of the components because in it all of the components annotated by @FXML are initialized. In your case, in start method is not yet initialized. Also you may don't want to use the scene's method, instead of you can add events, actions to your content pane, in your case to the AnchorPane.

I would suggest to separate the controller class from your main class, and implement Initializable. This helps you to have a better vision over your application, you cans see where exactly your components are initialized, were are you sure about using their methods, without NPE.

If you don't want to do it in a separate class(which is recommended) you can add an fx:id for AnchorPane in the .fxml file, then you can add the method to onKeyPressed like you did for the Button.

Sunflame
  • 2,993
  • 4
  • 24
  • 48
  • Thanks for your answer. I am teaching javafx myself and just learned that my `Application` class should not be the `Controller` class. Your tipp on using an `onKeyPressed` event on ex. the content pane is also valid, still I will seperate `Controller` and `Application` to do it the right way. Other readers: I found this excellent explanation on why to seperate them: https://stackoverflow.com/questions/33303167/javafx-can-application-class-be-the-controller-class – midorlo Oct 10 '17 at 07:12