Функция доступа JavaFX в классе контроллера из основного

Это я бьюсь головой о стену!!!! Надеясь, что кто-то может указать мне в правильном направлении. Я уверен, что делаю что-то СОВЕРШЕННО ГЛУПОЕ И ТУПОЕ. Я искал и искал, но не могу понять, почему это НЕ работает!! (Использование JDK8.x с компоновщиком сцен в IntelliJ IDE 15.x). Я пытаюсь отобразить данные в графическом интерфейсе, но хочу, чтобы эти данные программно отправлялись на него из других классов/методов.... вот простая концепция, которую я пытаюсь заставить работать, прежде чем работать над моим более крупным проектом:

Main Class:

package sample;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

Controller myController = new Controller();

@Override
public void start(Stage primaryStage) throws Exception{
    Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
    primaryStage.setTitle("Hello World");
    primaryStage.setScene(new Scene(root, 345, 200));
    primaryStage.show();
    myController.pushBtn();
}

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

Мой простой графический интерфейс, определенный в FXML с классом контроллера Scenebuilder:

package sample;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;

public class Controller {

@FXML // ResourceBundle that was given to the FXMLLoader
private ResourceBundle resources;

@FXML // URL location of the FXML file that was given to the FXMLLoader
private URL location;

@FXML // fx:id="txtBox"
private TextField txtBox; // Value injected by FXMLLoader

@FXML // fx:id="myButton"
private Button myButton; // Value injected by FXMLLoader

@FXML // This method is called by the FXMLLoader when initialization is   complete
void initialize() {
    assert txtBox != null : "fx:id=\"txtBox\" was not injected: check your   FXML file 'sample.fxml'.";
    assert myButton != null : "fx:id=\"myButton\" was not injected: check     our FXML file 'sample.fxml'.";
}
@FXML
private void pressBtn(ActionEvent event){
    txtBox.setText("Btn was pushed...");
}

@FXML
public void pushBtn(){
    txtBox.appendText("Sample from Main");
}

}

.. и, наконец, мой очень простой файл FXML вместе с тегами идентификатора и обработчика событий:

<GridPane alignment="center" hgap="10" vgap="10"      xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.65"       fx:controller="sample.Controller">
  <columnConstraints>
  <ColumnConstraints />
  </columnConstraints>
  <rowConstraints>
    <RowConstraints />
 </rowConstraints>
 <children>
   <Pane prefHeight="200.0" prefWidth="345.0" style="-fx-background-color:  GRAY;">
       <children>
         <TextField fx:id="txtBox" layoutX="63.0" layoutY="28.0"     prefHeight="53.0" prefWidth="224.0" style="-fx-background-color: LIGHTGRAY;" />
          <Button fx:id="myButton" layoutX="140.0" layoutY="100.0"  mnemonicParsing="false" onAction="#pressBtn" text="Button" />
       </children>
      </Pane>
  </children>
 </GridPane>

Все, что я пытаюсь сделать, это вызвать функцию, которая была объявлена ​​общедоступной в классе контроллера, и заставить эту функцию поместить текст в мой txtBox, который, как вы можете видеть, был определен с помощью FXML. Я создаю экземпляр этого класса контроллера в main, а затем использую этот экземпляр для доступа к этому методу. Все, что я читал и искал здесь, указывает на то, что это правильный способ сделать это. Однако это НИКОГДА не работает, и все, что я получаю, это ошибка как таковая:

Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in   Application start method
  at      com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at    com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImp    l.java:182)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
    at sample.Controller.pushBtn(Controller.java:43)
at sample.Main.start(Main.java:20)
at    com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherIm    pl.java:863)
at     com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
at    com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at    com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at     com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at     com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
... 1 more `

Что, черт возьми, мне не хватает? Есть ли другой способ назвать это, я что-то не инициализирую? ОЧЕНЬ ценим любую обратную связь!!!


person CYBORGCNC    schedule 11.04.2016    source источник
comment
Похоже, что ваш txtBox в вызове PushBtn равен нулю. Возможно, инициализация еще не завершена к тому времени, когда вы попытаетесь вызвать ее вручную.   -  person Steven Hansen    schedule 12.04.2016
comment
Я создаю экземпляр этого класса контроллера в main. Ну, это проблема. Этот экземпляр не является контроллером.   -  person James_D    schedule 12.04.2016


Ответы (1)


Вы создаете второй экземпляр Controller при вызове new Controller(). Это, конечно, не тот экземпляр Controller, который был создан FXMLLoader при загрузке файла FXML, поэтому ни одно из полей, введенных @FXML, не будет инициализировано.

Вам нужно получить экземпляр Controller из FXMLLoader:

package sample ;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {


    @Override
    public void start(Stage primaryStage) throws Exception{
        FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
        Parent root = loader.load();

        Controller myController = loader.getController();

        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 345, 200));
        primaryStage.show();
        myController.pushBtn();

   }

   public static void main(String[] args) {
       launch(args);
   }
}
person James_D    schedule 11.04.2016
comment
ТЫ ГЕНИЙ!!! Большое спасибо, что выбрали это! Это точно была моя ГЛУПАЯ проблема.... Еще раз спасибо! - person CYBORGCNC; 12.04.2016