JavaFX FXML doesn't see my controller methods correctly "Controller is not defined on root component" when using fxml as component within fxml

10,771

Solution 1

It works quite well with:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class LoadOwnFXML extends Application {

    @Override
    public void start(Stage primaryStage) {


            Scene scene = new Scene(new ProfilPane());
            primaryStage.setTitle("Hello World!");
            primaryStage.setScene(scene);
            primaryStage.show();
    }

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

}

And the ProfilePane class

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.AnchorPane;

public class ProfilPane extends AnchorPane {

    public ProfilPane() {
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("my.fxml"));
            loader.setRoot(this);
            loader.setController(this);
            loader.load();
        } catch (IOException ex) {
            Logger.getLogger(ProfilPane.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @FXML
    public void select() {
        System.out.println("selected");
    }

    @FXML
    public void hoverOver() {
        System.out.println("hovered");
    }

    @FXML
    public void hoverOut() {
        System.out.println("hovered out");
    }
}

The FXML File

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

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<fx:root fx:id="profilePane" onMouseClicked="#select" onMouseEntered="#hoverOver" onMouseExited="#hoverOut" type="javafx.scene.layout.Pane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children><AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="384.0" prefWidth="270.0" style="-fx-border-color: #40464A;">
<children>
<StackPane prefHeight="430.0" prefWidth="270.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Pane prefWidth="270.0">
<children><ImageView fitHeight="288.0" fitWidth="270.0" layoutY="49.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../resources/images/category/TechnologyTemp.png" />
</image>
<StackPane.margin>
<Insets top="45.0" />
</StackPane.margin>
<viewport>
<Rectangle2D />
</viewport></ImageView>
</children>
</Pane><BorderPane layoutX="79.0" layoutY="100.0" prefHeight="258.0" prefWidth="270.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<top>
<Pane prefHeight="49.0" prefWidth="268.0" style="-fx-background-color: white;">
<children><VBox prefHeight="143.0" prefWidth="270.0" BorderPane.alignment="CENTER">
<children><Label text="Adobe">
<font>
<Font name="System Bold" size="15.0" />
</font>
<padding>
<Insets left="10.0" top="5.0" />
</padding>
</Label><Label text="Adobe Systems,inc">
<font>
<Font name="System Bold" size="14.0" />
</font>
<padding>
<Insets bottom="3.0" left="10.0" />
</padding>
</Label>
<Pane layoutX="-1.0" opacity="0.82" prefHeight="82.0" prefWidth="220.0">
<children><TextArea cache="true" editable="false" focusTraversable="false" mouseTransparent="true" pickOnBounds="false" prefHeight="82.0" prefWidth="268.0" style="-fx-background-radius: 0;" text="Oracle continually applies good corporate governance principles. The composition and activities of the company's Board of Directors, the approach to public disclosure" wrapText="true">
<VBox.margin>
<Insets top="53.0" />
</VBox.margin></TextArea>
</children>
</Pane>
</children></VBox>
</children>
</Pane>
</top>
<bottom>
<Pane prefHeight="45.0" prefWidth="270.0" style="-fx-background-color: white;">
<children><VBox prefHeight="55.0" prefWidth="270.0" BorderPane.alignment="CENTER">
<children><Label text="Technology">
<font>
<Font name="System Bold" size="14.0" />
</font>
<padding>
<Insets left="10.0" top="4.0" />
</padding>
</Label><Label text="Software services &amp; provider">
<padding>
<Insets left="10.0" />
</padding>
<font>
<Font size="13.0" />
</font></Label>
</children></VBox>
</children>
</Pane>
</bottom></BorderPane>
</children>
</StackPane><Pane prefHeight="382.0" prefWidth="270.0">
<children><ToggleButton fx:id="toggleButton" layoutX="1.0" layoutY="191.0" mnemonicParsing="false" prefHeight="30.0" prefWidth="268.0" style="-fx-background-radius: 0; -fx-background-color: #57A1DE;" text="Select profile" textFill="WHITE">
<font>
<Font name="System Bold" size="14.0" />
</font></ToggleButton>
</children></Pane>
</children></AnchorPane>
</children>
</fx:root>

Solution 2

Try removing the fx:id attribute from the <fx:root ...> element, and the corresponding profilePane field from the Java code. These are redundant, since in the Java code the root element is simply this. I suspect that's just confusing your IDE.

Not relevant to your question, but you need to initialize your FadeTransition in the initialize() method, since the toggleButton won't have been initialized until that is called. And there is no need for the Platform.runLater(...) calls; the event handlers will be invoked on the FX Application Thread anyway.

Share:
10,771
Tomas Bisciak
Author by

Tomas Bisciak

Java programmer ,CS bachelors degree from the University of Ss. Cyril and Methodius in Trnava. Constantly trying to improve my skills :) I welcome edits to my answers/questions.

Updated on June 07, 2022

Comments

  • Tomas Bisciak
    Tomas Bisciak almost 2 years

    I'm creating rich ui application and I use FXML within FXML and every part have separate controllers. I decided to follow this tutorial and use my fxml as component. So I use class as a controller and component. Everything seems to be working but I hit a wall when I try to put methods into my class/controller. I edited my FXML so I don't put controller directly into it. But using class itself. this is where the problematic line is

    <fx:root fx:id="profilePane" onMouseClicked="#select" onMouseEntered="#hoverOver" onMouseExited="#hoverOut" type="javafx.scene.layout.Pane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">...etc
    

    every method is red saying that Controller is not defined on root component well I know that I removed that part from my fxml. But how would it work on tutorial that I follow? Here is my component class what I work with

    imports etc..
    public class FxmlProfilePanel extends Pane implements Initializable{
    
        @FXML
        private ToggleButton toggleButton;
    
        @FXML
        private Pane profilePane;
    
        private FadeTransition fadeTransition=new FadeTransition(Duration.millis(500),toggleButton);
    
    
        /**
         * Initializes the controller class.
         */
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            // TODO
    
    
            System.out.println("Is fx thread?:"+Platform.isFxApplicationThread());
        }   
    
        public FxmlProfilePanel(){
            FXMLLoader fxmlLoader=new FXMLLoader(getClass().getResource("/bitcompile/ecps/fxml/FxmlProfilePanel.fxml"));
            fxmlLoader.setRoot(this);
            fxmlLoader.setController(this);
            try {
                fxmlLoader.load();
            } catch (IOException ex) {
                Logger.getLogger(FxmlProfilePanel.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    
    
        public void hoverOver(MouseEvent event){
            Platform.runLater(() -> {
                if(!toggleButton.isSelected()){
                toggleButton.setText("Select profile");
                fadeTransition.setFromValue(0);
                fadeTransition.setToValue(1.0);
                fadeTransition.play();
    
                }else{
                toggleButton.setText("Deselect profile");
                fadeTransition.setFromValue(0);
                fadeTransition.setToValue(1.0);
                fadeTransition.play();
                }
            });
        }
    
          public void hoverOut(MouseEvent event){
            Platform.runLater(() -> {
                if(toggleButton.isSelected())
                fadeTransition.setFromValue(1.0);
                fadeTransition.setToValue(0);
                fadeTransition.play();
            });
        }
    
        public void selected(MouseEvent event){
            if(!toggleButton.isSelected()){
              toggleButton.setSelected(true);
              toggleButton.setText("Profile Selected");
    
            }else{
                toggleButton.setSelected(false);
                toggleButton.setText("Select profile");
            }
        }
    }
    

    So question is.When I use fxml/controller as component inside another fxml which is within another fxml etc. how do I connect my methods from within my component class? (I know how to do all this following normal fxml style with separate controller etc, but not this way).. Did I pick the wrong way of doing this? Should I consider another approach? thx for any insight.

    full fxml code:

    <fx:root fx:id="profilePane" onMouseClicked="#select" onMouseEntered="#hoverOver" onMouseExited="#hoverOut" type="javafx.scene.layout.Pane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
    <children><AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="384.0" prefWidth="270.0" style="-fx-border-color: #40464A;">
    <children>
    <StackPane prefHeight="430.0" prefWidth="270.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
    <children>
    <Pane prefWidth="270.0">
    <children><ImageView fitHeight="288.0" fitWidth="270.0" layoutY="49.0" pickOnBounds="true" preserveRatio="true">
    <image>
    <Image url="@../resources/images/category/TechnologyTemp.png" />
    </image>
    <StackPane.margin>
    <Insets top="45.0" />
    </StackPane.margin>
    <viewport>
    <Rectangle2D />
    </viewport></ImageView>
    </children>
    </Pane><BorderPane layoutX="79.0" layoutY="100.0" prefHeight="258.0" prefWidth="270.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
    <top>
    <Pane prefHeight="49.0" prefWidth="268.0" style="-fx-background-color: white;">
    <children><VBox prefHeight="143.0" prefWidth="270.0" BorderPane.alignment="CENTER">
    <children><Label text="Adobe">
    <font>
    <Font name="System Bold" size="15.0" />
    </font>
    <padding>
    <Insets left="10.0" top="5.0" />
    </padding>
    </Label><Label text="Adobe Systems,inc">
    <font>
    <Font name="System Bold" size="14.0" />
    </font>
    <padding>
    <Insets bottom="3.0" left="10.0" />
    </padding>
    </Label>
    <Pane layoutX="-1.0" opacity="0.82" prefHeight="82.0" prefWidth="220.0">
    <children><TextArea cache="true" editable="false" focusTraversable="false" mouseTransparent="true" pickOnBounds="false" prefHeight="82.0" prefWidth="268.0" style="-fx-background-radius: 0;" text="Oracle continually applies good corporate governance principles. The composition and activities of the company's Board of Directors, the approach to public disclosure" wrapText="true">
    <VBox.margin>
    <Insets top="53.0" />
    </VBox.margin></TextArea>
    </children>
    </Pane>
    </children></VBox>
    </children>
    </Pane>
    </top>
    <bottom>
    <Pane prefHeight="45.0" prefWidth="270.0" style="-fx-background-color: white;">
    <children><VBox prefHeight="55.0" prefWidth="270.0" BorderPane.alignment="CENTER">
    <children><Label text="Technology">
    <font>
    <Font name="System Bold" size="14.0" />
    </font>
    <padding>
    <Insets left="10.0" top="4.0" />
    </padding>
    </Label><Label text="Software services &amp; provider">
    <padding>
    <Insets left="10.0" />
    </padding>
    <font>
    <Font size="13.0" />
    </font></Label>
    </children></VBox>
    </children>
    </Pane>
    </bottom></BorderPane>
    </children>
    </StackPane><Pane prefHeight="382.0" prefWidth="270.0">
    <children><ToggleButton fx:id="toggleButton" layoutX="1.0" layoutY="191.0" mnemonicParsing="false" prefHeight="30.0" prefWidth="268.0" style="-fx-background-radius: 0; -fx-background-color: #57A1DE;" text="Select profile" textFill="WHITE">
    <font>
    <Font name="System Bold" size="14.0" />
    </font></ToggleButton>
    </children></Pane>
    </children></AnchorPane>
    </children>
    </fx:root>
    
    • James_D
      James_D about 10 years
      Is <fx:root ...> the root element of your FMXL file? I think that's the only place it is valid.
    • Tomas Bisciak
      Tomas Bisciak about 10 years
      @James_D Yes thats the root element then children goes bellow it.So far whole ui is decoupled.This component shoud work by iself without any dependencies,hence thats why i made it as component.Bud i cant make those methods work no matter what i try.
    • James_D
      James_D about 10 years
      So where are the errors? Are they compile errors in the Java code?
    • Tomas Bisciak
      Tomas Bisciak about 10 years
      exactly on the line i posted fx:root.. etc each method is market as red and when i hover over error is saying -Controller is not defined on root component.Bud every single method exists in my class and also fx:root is a root element.I will post whole fxml in addition to my question
    • James_D
      James_D about 10 years
      So it's just the IDE reporting the error, and it's in the FXML file, if I understand you correctly. Have you tried to see if it works anyway, since FXML isn't compiled?
    • Tomas Bisciak
      Tomas Bisciak about 10 years
      Yes thats correct.No i didnt tryed it yet, i seen this as a red flag and didnt proceed bud i will give it a shot and report in shortly.
  • Patrick
    Patrick about 10 years
    Which errors you see? Maybe you need some imports? Please post the errors you get, that i can have a look how can it be solved.