Почему я не могу использовать F XML с контроллерами и fxid в контроллере? - PullRequest
0 голосов
/ 18 июня 2020

Я нашел здесь то, что мне нужно. Мне нужен доступ от одного контроллера к другому.

Но у меня есть вопрос. Почему, когда я использую аннотацию F XML, я получаю исключение?

Я хочу сделать

public class MainController {
    @FXML Tab1Controller tab1Controller;
    @FXML Tab2Controller tab2Controller;

    @FXML Tab tab1;   //THIS
    @FXML Tab tab2;   // And this call exception. But if i comment both fields is evertying OK.


    @FXML public void initialize() {
        System.out.println("Application started");
        tab1Controller.init(this);
        tab2Controller.init(this);
    }

    public String loadLblTextFromTab1() {
        return tab1Controller.lbl1.getText();
    }

    public void setTab2LabelText(String text) {
        tab2Controller.lbl2.setText(text);
    }
}

PS добавить файл XML, где у меня есть этот fx: id

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

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

<AnchorPane prefHeight="299.0" prefWidth="309.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.MainController">
   <children>
      <TabPane prefHeight="299.0" prefWidth="309.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <tabs>
          <Tab closable="false" text="Tab 1">
               <content>
                  <fx:include fx:id="tab1" source="tab/Tab1.fxml" />
               </content></Tab>
          <Tab closable="false" text="Tab 2">
               <content>
                  <fx:include fx:id="tab2" source="tab/Tab2.fxml" />
               </content></Tab>
        </tabs>
      </TabPane>
   </children>
</AnchorPane>

PSS.

Если я использую свой F XML и Class, как этот, я получу NullPointerException из-за tab1Controller == null

 public class MainController {
    @FXML Tab tab1;
    @FXML Tab1Controller tab1Controller;

    @FXML public void initialize() {
        tab1Controller.init(this); // Line 15
    }
}

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

<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
            fx:controller="controller.MainController">
    <TabPane>
        <Tab fx:id="tab1" closable="false" text="Tab 1">
            <fx:include source="tab/Tab1.fxml"/>
        </Tab>
    </TabPane>
</AnchorPane>

Исключение выглядит как

Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2566)
    ... 17 more
Caused by: java.lang.NullPointerException
    at controller.MainController.initialize(MainController.java:15)
    ... 27 more

Итак, теперь я не могу понять, почему я получаю это исключение? В любом случае я сгенерировал свой Tab из самого файла f xml.

1 Ответ

2 голосов
/ 18 июня 2020

Сообщение об ошибке:

Caused by: java.lang.IllegalArgumentException: 
  Can not set javafx.scene.control.Tab field controller.MainController.tab1 to javafx.scene.layout.AnchorPane

объясняет, в чем проблема. <fx:include> генерирует AnchorPane (предположительно, это элемент root из Tab1.fxml), и вы пытаетесь использовать поле типа Tab для ссылки на него.

Если вы только требуется доступ к содержимому вкладки, просто измените тип поля соответствующим образом:

public class MainController {
    @FXML Tab1Controller tab1Controller;
    @FXML Tab2Controller tab2Controller;

    @FXML AnchorPane tab1;   
    @FXML AnchorPane tab2;   


    @FXML public void initialize() {
        System.out.println("Application started");
        tab1Controller.init(this);
        tab2Controller.init(this);
    }

    public String loadLblTextFromTab1() {
        return tab1Controller.lbl1.getText();
    }

    public void setTab2LabelText(String text) {
        tab2Controller.lbl2.setText(text);
    }
}

Если вам специально нужен доступ к самим вкладкам, вам понадобится fx:id s на Tab. Как и раньше, чтобы получить ссылку на контроллер, вам понадобится fx:id на <fx:include>. Поэтому, если вам нужна фактическая ссылка на Tab, а также на контроллер, вам понадобятся (разные) fx:id s как на Tab, так и на <fx:include>:

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

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

<AnchorPane prefHeight="299.0" prefWidth="309.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.MainController">
   <children>
      <TabPane prefHeight="299.0" prefWidth="309.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <tabs>
          <Tab fx:id="tab1" closable="false" text="Tab 1">
               <content>
                  <fx:include fx:id="tab1Content" source="tab/Tab1.fxml" />
               </content></Tab>
          <Tab fx:id="tab2" closable="false" text="Tab 2">
               <content>
                  <fx:include fx:id="tab2Content" source="tab/Tab2.fxml" />
               </content></Tab>
        </tabs>
      </TabPane>
   </children>
</AnchorPane>

и

public class MainController {
    @FXML Tab1Controller tab1ContentController;
    @FXML Tab2Controller tab2ContentController;

    @FXML Tab tab1;   
    @FXML Tab tab2;   


    @FXML public void initialize() {
        System.out.println("Application started");
        tab1Controller.init(this);
        tab2Controller.init(this);
    }

    public String loadLblTextFromTab1() {
        return tab1ContentController.lbl1.getText();
    }

    public void setTab2LabelText(String text) {
        tab2ContentController.lbl2.setText(text);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...