JavaFX getText (), setText (), toString () дают нулевые указатели

Controller.java

import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;

public class Controller {

    public TextField txtField;
    public PasswordField passField;
    public Button btn;
    public Label access;

    private String USNM = "crimsoncoder";
    private String PASS = "toor";

▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬Проблема начинается здесь▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬

    private String usnm = txtField.getText();
    private String pass = passField.getText();
    private String acc = access.getText();

    private final String ACCESS_GRANTED = "/ACCESS_GRANTED/";
    private final String ACCESS_DENIED = "|/?ACCESS_DENIED?/|";

    public void onClick() {
        if (usnm.equals(USNM)) {
            if (pass.equals(PASS)) {
                acc = ACCESS_GRANTED;
            } else {
                acc = ACCESS_DENIED;
            }
        } else {
            acc = ACCESS_DENIED;
        }
    }
}

Вызов методов getText(), setText() и toString() после объявления переменных usnm, pass и acc в Controller.java возвращает NullPointerException. Есть идеи, почему это происходит?


Новый код:

public class Controller {

    @FXML
    private TextField txtField;
    @FXML
    private PasswordField passField;
    @FXML
    private Button btn;
    @FXML
    private Label access;

    private String USNM = "crimsoncoder";
    private String PASS = "toor";

    private static final String ACCESS_GRANTED = "/ACCESS_GRANTED/";
    private static final String ACCESS_DENIED = "|/?ACCESS_DENIED?/|";

    public void onClick() {
        String usnm = txtField.getText();
        String pass = passField.getText();

        if (usnm.equals(USNM)) {
            if (pass.equals(PASS)) {
                access.setText(ACCESS_GRANTED);
            } else {
                access.setText(ACCESS_DENIED);
            }
        } else {
            access.setText(ACCESS_DENIED);
        }
    }
}

Аннотируйте свои элементы управления с помощью @FXML в контроллере. Например, @FXML TextField txtField;

ItachiUchiha 02.06.2018 22:25

Это не поможет, так как а) поля относятся к public и, следовательно, подходят для инъекции, и б) это не приведет к тому, что поля будут введены до запуска инициализатора. OP необходимо получить значение из полей в обработчике событий. Также предпочтительно использовать onAction вместо onMouseClicked ... Более того, метод обработчика не будет иметь никакого эффекта, поскольку поле acc никогда не читается.

fabian 02.06.2018 22:35
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
421
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я предлагаю вам не использовать переменные экземпляра, а локальную переменную. Другими словами, перепишите свой метод таким образом:

public void onClick(){
        String usnm = txtField.getText();
        String pass = passField.getText();
        ...
}

Надеюсь, это поможет.

P.S. Похоже, что ACCESS_GRANTED и ACCESS_DENIED должны быть константами, поэтому добавьте для них статический идентификатор.

это потому, что при инициализации контроллера класса он запускает переменную экземпляра из другой переменной экземпляра, которая имеет значение NULL. Мое предложение переместить это

private String usnm = txtField.getText();
private String pass = passField.getText();
private String acc = access.getText();

методу, который срабатывает, когда кто-то заполняет эти поля, и позволяет создать переменную экземпляра null.

бывший.

private String usnm 
private String pass
private String acc

Но:

Я вижу, вы пытаетесь сделать это как MVC - я думаю, вы делаете это неправильно - прочтите что-нибудь об этом шаблоне.

Ответ принят как подходящий

На самом деле здесь довольно много проблем с вашим дизайном. Прежде всего, вы пытаетесь получить доступ к значениям элементов управления txtField и passField до того, как эти элементы управления фактически появятся в сцене.

В JavaFX и FXML эти элементы управления не создаются (или не внедряются) и не доступны контроллеру до тех пор, пока сцена не будет инициализирована.

Ссылки на элементы управления также должны быть private и аннотированы ключевым словом @FXML, например:

@FXML
private TextField txtField;

По сути, это сообщает Java, что TextField уже определен в соответствующем документе FXML.

И вам нужно получить значения полей имени пользователя и пароля после, когда была нажата кнопка LOGIN, поэтому обновите свой метод onClick(), чтобы получить значения в это время:

public void onClick() {

        String usnm = txtField.getText();
        String pass = passField.getText();

        String acc;

        if (usnm.equals(USNM)) {
            if (pass.equals(PASS)) {
                acc = ACCESS_GRANTED;
            } else {
                acc = ACCESS_DENIED;
            }
        } else {
            acc = ACCESS_DENIED;
        }

        System.out.println(acc);
    }

Итак, для немного лучшего Controller.java вы можете использовать что-то вроде этого:

public class Controller {

    @FXML
    public TextField txtField;
    @FXML
    public PasswordField passField;
    @FXML
    public Button btn;
    @FXML
    public Label access;

    private String USNM = "crimsoncoder";
    private String PASS = "toor";

    private static final String ACCESS_GRANTED = "/ACCESS_GRANTED/";
    private static final String ACCESS_DENIED = "|/?ACCESS_DENIED?/|";

    public void onClick() {

        String usnm = txtField.getText();
        String pass = passField.getText();

        String acc;

        if (usnm.equals(USNM)) {
            if (pass.equals(PASS)) {
                acc = ACCESS_GRANTED;
            } else {
                acc = ACCESS_DENIED;
            }
        } else {
            acc = ACCESS_DENIED;
        }

        System.out.println(acc);
    }

}

Вам не нужна аннотация @FXML для общедоступного поля (хотя на самом деле поля должны быть частными ...)

James_D 02.06.2018 23:41

О, хороший улов. Я обновлю их до частных, так как я никогда не использую для них общедоступные.

Zephyr 02.06.2018 23:42

Другие вопросы по теме