2015-06-17 63 views
3

我正在學習編寫用於JavaFX 8和Scene Builder的FXML自定義組件。這個JavaFX/FXML自定義組件有什麼問題?

我寫了下面,但場景生成器表示不會打開它的FXML文件,給我的消息「打開操作失敗」,由於異常:

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

爲什麼會出現這種異常?

這裏的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> 

這裏是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

你可以嘗試添加import語句 「<?進口mycustomcomponent。*?>」,在FXML?你的代碼在eclipse中工作正常。可能它是一個NetBeans的東西,因爲它從src文件夾而不是部署文件夾獲取fxml? – Roland

+1

您是否將包含自定義組件的jar文件導入到sceneBuilder中? – griFlo

+0

@Roland。謝謝。實際上,因爲我使用了全限定名稱,所以不需要導入語句。該代碼也適用於NetBeans,但它不適用於Scene Builder。爲了實現這一點,type屬性必須是AnchorPane,並且需要將自定義組件導入到Scene Builder中(這很奇怪,因爲我正在開發它)。 – user118967

回答

5

這是一個有點棘手。所以,你的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> 

在這之後,你必須做它的一個罐子,因爲你有一個fxml和一個java類。這是NetBeans中的棘手的部分,所以跟進:

第一:創建看起來像這樣與你複製源文件組件中的自己圖書館項目:

enter image description here

第二:刪除複製的主(其中的主要方法是在)文件

三:做一個「克麗n和Build「。生成的.jar文件將位於Project目錄中的子文件夾「dist」中。

四:打開的場景生成器,並導入CustomComponent .jar文件是這樣的:

enter image description here

enter image description here

現在,您可以爲您要使用的組件。但要注意對組件的更改不是動態刷新導入的jar,你必須再次完成整個過程。

+0

謝謝。 其實FXML工程,即使類型是mycustomcomponent.TicoTeco,但場景生成器將不會導入它這樣。這是否意味着SB只會導入來自標準JavaFX控件的東西,比如AnchorPane?這是令人失望的,因爲這意味着定製組件並不像標準組件那樣被處理。例如,你不能從另一個自定義組件定義一個自定義組件,那麼呢? – user118967

+0

所以,這是一個編程範例,你應該總是使用可能的超類型或接口。所以即使是一個子子組件也是從AnchorPane派生的。一個真的組件看起來的另一種方式,你可以在JavaFX的來源看,還有比只喜歡AnchorPane類這麼多。 – NwDev