这个JavaFX / FXML自定义组件有什么问题?

时间:2021-08-19 13:57:54

I am learning to write FXML custom components for use with JavaFX 8 and Scene Builder.

我正在学习编写用于JavaFX 8和Scene Builder的FXML自定义组件。

I wrote the FXML file shown below but Scene Builder will not open it, giving me the message "Open operation has failed" due to the exception:

我编写了下面显示的FXML文件,但是Scene Builder不会打开它,因为例外情况给我发出消息“Open operation failed”:

java.io.IOException: javafx.fxml.LoadException: mycustomcomponent.TicoTeco is not a valid type.
/C:/Users/xxxxx/Documents/NetBeansProjects/MyCustomComponent/src/mycustomcomponent/TicoTeco.fxml:9
    at com.oracle.javafx.scenebuilder.kit.fxom.FXOMLoader.load(FXOMLoader.java:92)
    at com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument.(FXOMDocument.java:80)
    at com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument.(FXOMDocument.java:95)
...

Why am I getting this exception?

为什么我得到这个例外?

Here's the FXML file:

这是FXML文件:

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

<fx:root type="mycustomcomponent.TicoTeco" prefHeight="93.0" prefWidth="304.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <BorderPane layoutX="61.0" prefHeight="115.0" prefWidth="200.0">
         <left>
            <Button fx:id="tico" mnemonicParsing="false" text="Tico" BorderPane.alignment="CENTER" />
         </left>
         <right>
            <Button fx:id="teco" mnemonicParsing="false" text="Teco" BorderPane.alignment="CENTER" />
         </right>
      </BorderPane>
   </children>
</fx:root>

And here are the Java files for TicoTeco.java and Main.java:

以下是TicoTeco.java和Main.java的Java文件:

package mycustomcomponent;

import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;

public class TicoTeco extends AnchorPane {

    @FXML
    Button tico;

    @FXML
    Button teco;

    public TicoTeco() throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(TicoTeco.class.getResource("TicoTeco.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);
        fxmlLoader.load();
    }

    @FXML
    public void initialize() {
        final EventHandler<ActionEvent> onAction = 
                event -> System.out.println("Hi, I'm " + (event.getSource() == tico? "Tico" : "Teco") + "!");
        tico.setOnAction(onAction);
        teco.setOnAction(onAction);
    }
}
package mycustomcomponent;

import java.io.IOException;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws IOException {
        Scene scene = new Scene(new TicoTeco());

        primaryStage.setTitle("Here are Tico and Teco!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

1 个解决方案

#1


5  

It's a bit tricky. So your fxml have a little mistake:

这有点棘手。所以你的fxml有一点错误:

Your custom class is extending AnchorPane, so this should be the root in your fxml:

您的自定义类正在扩展AnchorPane,因此这应该是您的fxml中的根:

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

<fx:root type="AnchorPane" prefHeight="93.0" prefWidth="304.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <BorderPane layoutX="61.0" prefHeight="115.0" prefWidth="200.0">
         <left>
            <Button fx:id="tico" mnemonicParsing="false" text="Tico" BorderPane.alignment="CENTER" />
         </left>
         <right>
            <Button fx:id="teco" mnemonicParsing="false" text="Teco" BorderPane.alignment="CENTER" />
         </right>
      </BorderPane>
   </children>
</fx:root>

After that, you have to make a jar of it, because you have a fxml and a java class. This is the tricky part in Netbeans, so follow up:

之后,你必须制作一个jar,因为你有一个fxml和一个java类。这是Netbeans中棘手的部分,所以跟进:

First: Create an own Library Project for the component that looks like this with your copied source files:

第一步:使用复制的源文件为组件创建一个自己的库项目:

这个JavaFX / FXML自定义组件有什么问题?

Second: Delete the copied Main (where the main method is in) file

第二步:删除复制的Main(主方法所在的位置)文件

Third: Do a "Clean and Build" at the project. The generated .jar file will be in the subfolder "dist" in your Project directory.

第三:在项目中进行“清理和建设”。生成的.jar文件将位于Project目录的子文件夹“dist”中。

Fourth: Open Scene Builder and import your CustomComponent .jar file like this:

第四步:打开Scene Builder并导入CustomComponent .jar文件,如下所示:

这个JavaFX / FXML自定义组件有什么问题?

这个JavaFX / FXML自定义组件有什么问题?

Now you are able to use the component as you want. But be aware of changes to the component are not dynamicaly refresh the imported jar, you have to do the whole thing again.

现在,您可以根据需要使用该组件。但要注意组件的更改不是动态刷新导入的jar,你必须再做一遍。

#1


5  

It's a bit tricky. So your fxml have a little mistake:

这有点棘手。所以你的fxml有一点错误:

Your custom class is extending AnchorPane, so this should be the root in your fxml:

您的自定义类正在扩展AnchorPane,因此这应该是您的fxml中的根:

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

<fx:root type="AnchorPane" prefHeight="93.0" prefWidth="304.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <BorderPane layoutX="61.0" prefHeight="115.0" prefWidth="200.0">
         <left>
            <Button fx:id="tico" mnemonicParsing="false" text="Tico" BorderPane.alignment="CENTER" />
         </left>
         <right>
            <Button fx:id="teco" mnemonicParsing="false" text="Teco" BorderPane.alignment="CENTER" />
         </right>
      </BorderPane>
   </children>
</fx:root>

After that, you have to make a jar of it, because you have a fxml and a java class. This is the tricky part in Netbeans, so follow up:

之后,你必须制作一个jar,因为你有一个fxml和一个java类。这是Netbeans中棘手的部分,所以跟进:

First: Create an own Library Project for the component that looks like this with your copied source files:

第一步:使用复制的源文件为组件创建一个自己的库项目:

这个JavaFX / FXML自定义组件有什么问题?

Second: Delete the copied Main (where the main method is in) file

第二步:删除复制的Main(主方法所在的位置)文件

Third: Do a "Clean and Build" at the project. The generated .jar file will be in the subfolder "dist" in your Project directory.

第三:在项目中进行“清理和建设”。生成的.jar文件将位于Project目录的子文件夹“dist”中。

Fourth: Open Scene Builder and import your CustomComponent .jar file like this:

第四步:打开Scene Builder并导入CustomComponent .jar文件,如下所示:

这个JavaFX / FXML自定义组件有什么问题?

这个JavaFX / FXML自定义组件有什么问题?

Now you are able to use the component as you want. But be aware of changes to the component are not dynamicaly refresh the imported jar, you have to do the whole thing again.

现在,您可以根据需要使用该组件。但要注意组件的更改不是动态刷新导入的jar,你必须再做一遍。