简体   繁体   English

当fxml作为fxml中的组件使用时,JavaFX FXML没有正确地看到我的控制器方法“未在根组件上定义控制器”

[英]JavaFX FXML doesn't see my controller methods correctly “Controller is not defined on root component” when using fxml as component within fxml

I'm creating rich ui application and I use FXML within FXML and every part have separate controllers. 我正在创建丰富的ui应用程序,我在FXML中使用FXML,每个部分都有独立的控制器。 I decided to follow this tutorial and use my fxml as component. 我决定按照教程使用我的fxml作为组件。 So I use class as a controller and component. 所以我使用class作为控制器和组件。 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. 我编辑了我的FXML,所以我不直接将控制器放入其中。 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. 每个方法都是红色的,说控制器没有很好地定义在根组件上我知道我从我的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? 当我使用fxml / controller作为另一个fxml中的另一个fxml内的组件时,如何从我的组件类中连接我的方法? (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? (我知道如何使用单独的控制器等以正常的fxml风格完成所有这些,但不是这样)..我选择了错误的方法吗? Should I consider another approach? 我应该考虑另一种方法吗? thx for any insight. thx任何见解。

full fxml code: 完整的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>

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

The FXML File 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>

Try removing the fx:id attribute from the <fx:root ...> element, and the corresponding profilePane field from the Java code. 尝试从<fx:root ...>元素中删除fx:id属性,并从Java代码中删除相应的profilePane字段。 These are redundant, since in the Java code the root element is simply this . 这些是多余的,因为在Java代码中,根元素就是this I suspect that's just confusing your IDE. 我怀疑这只会让你的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. 与您的问题无关,但您需要在initialize()方法中初始化您的FadeTransition ,因为toggleButton在调用之前不会被初始化。 And there is no need for the Platform.runLater(...) calls; 并且不需要Platform.runLater(...)调用; the event handlers will be invoked on the FX Application Thread anyway. 无论如何,将在FX Application Thread上调用事件处理程序。

What worked for me (NetBeans 8.1 with jdk8u74) was adding a fx:controller attribute to the root element of my .fxml file. 对我有用的(带有jdk8u74的NetBeans 8.1)是在我的.fxml文件的根元素中添加了一个fx:controller属性。 For example, with root element of GridPane and controller class FXMLTableViewController in the fxmltableview package: 例如,使用GridPane的根元素和fxmltableview包中的控制器类FXMLTableViewController:

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

Add fx:controller="packagename.FXMLDocumentController" class to the upper most parent in fxml document. fx:controller="packagename.FXMLDocumentController"类添加到fxml文档中最上面的父级。 For example, in my case I added into top VBox and have all components in child of VBox , that's why everything is working fine with me now. 例如,在我的情况下,我添加到顶级VBox并且所有组件都在VBox子代中,这就是为什么现在一切正常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM