【问题标题】:JavaFX FXML doesn't see my controller methods correctly "Controller is not defined on root component" when using fxml as component within fxml将 fxml 用作 fxml 中的组件时,JavaFX FXML 没有正确看到我的控制器方法“控制器未在根组件上定义”
【发布时间】:2014-06-11 04:56:19
【问题描述】:

我正在创建丰富的 ui 应用程序,我在 FXML 中使用 FXML,每个部分都有单独的控制器。我决定遵循this 教程并使用我的 fxml 作为组件。所以我使用类作为控制器和组件。一切似乎都在工作,但是当我尝试将方法放入我的类/控制器时我碰壁了。我编辑了我的 FXML,所以我没有将控制器直接放入其中。但是使用类本身。这就是问题所在

<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

每个方法都是红色的,表示 Controller 未在根组件上定义 我知道我从我的 fxml 中删除了该部分。但是它将如何在我遵循的教程中工作?这是我使用的组件类

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");
        }
    }
}

所以问题是。当我在另一个 fxml 中使用 fxml/controller 作为另一个 fxml 中的组件时,我如何从我的组件类中连接我的方法?(我知道该怎么做所有这些都遵循带有单独控制器等的正常 fxml 样式,但不是这种方式).. 我选择了错误的方式吗?我应该考虑另一种方法吗?感谢您提供任何见解。

完整的 fxml 代码:

<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>

【问题讨论】:

  • &lt;fx:root ...&gt; 是 FMXL 文件的根元素吗?我认为这是唯一有效的地方。
  • @James_D 是的,这就是根元素,然后孩子们就在下面。到目前为止,整个 ui 是解耦的。这个组件应该自己工作,没有任何依赖关系,因此这就是为什么我把它作为组件。但我不能无论我尝试什么,都要让这些方法发挥作用。
  • 那么错误在哪里?他们是否在 Java 代码中编译错误?
  • 正好在我发布 fx:root.. 等的行上,每种方法都是红色的,当我将鼠标悬停在错误上时,错误是说 -Controller 未在根组件上定义。Bud 每个方法都存在于我的类和 fx:root 也是一个根元素。除了我的问题,我将发布整个 fxml
  • 所以它只是 IDE 报告错误,它在 FXML 文件中,如果我理解正确的话。由于未编译 FXML,您是否尝试过查看它是否仍然有效?

标签: java javafx fxml scenebuilder


【解决方案1】:

fx:controller="packagename.FXMLDocumentController" 类添加到 fxml 文档中的最高父级。例如,在我的情况下,我添加到顶部 VBox 并在 VBox 的子项中添加了所有组件,这就是为什么现在一切正常。

【讨论】:

    【解决方案2】:

    对我有用(带有 jdk8u74 的 NetBeans 8.1)是在我的 .fxml 文件的根元素中添加一个 fx:controller 属性。例如,使用 GridPane 的根元素和 fxmltableview 包中的控制器类 FXMLTableViewController:

    <GridPane xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxmltableview.FXMLTableViewController">
    

    【讨论】:

      【解决方案3】:

      它适用于:

      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);
          }
      
      }
      

      还有 ProfilePane 类

      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");
          }
      }
      

      FXML 文件

      <?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>
      

      【讨论】:

      • 您看到了哪些错误?也许你需要一些进口?请发布您遇到的错误,我可以看看如何解决。
      【解决方案4】:

      尝试从&lt;fx:root ...&gt; 元素中删除fx:id 属性,并从Java 代码中删除相应的profilePane 字段。这些都是多余的,因为在 Java 代码中,根元素只是 this。我怀疑这只会让您的 IDE 感到困惑。

      与您的问题无关,但您需要在 initialize() 方法中初始化您的 FadeTransition,因为在调用该方法之前不会初始化 toggleButton。并且不需要Platform.runLater(...) 电话;无论如何,都会在 FX 应用程序线程上调用事件处理程序。

      【讨论】:

        猜你喜欢
        • 2015-05-29
        • 2018-09-15
        • 2013-07-22
        • 2016-08-20
        • 2013-12-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多