无法使用FXMLLoader在Clojure中加载FXML

时间:2013-05-18 11:04:30

标签: clojure javafx fxml

我正在尝试实现此处显示的基本JavaFX示例:http://docs.oracle.com/javafx/2/get_started/fxml_tutorial.htm。我能够得到基本的东西(以编程方式创建gui)并使用css,但我遇到了FXMLLoader的问题。

java版本是:

@Override
public void start(Stage stage) throws Exception {
   Parent root = FXMLLoader.load(getClass().getResource("fxml_example.fxml"));

    stage.setTitle("FXML Welcome");
    stage.setScene(new Scene(root, 300, 275));
    stage.show();
}

我不是Java专家,但我不认为FXMLLoader对象是实例化的,即。没有new FXMLLoader();声明。那么load来自哪里?

当我尝试以下clojure代码时:

(ns jfxtwo.core
  (:gen-class
   :extends javafx.application.Application)

  (:import (javafx.application Application)
           (javafx.fxml FXMLLoader)
           (javafx.scene Parent Scene)
           (javafx.stage Stage)))

(defn -main []
  (javafx.application.Application/launch jfxtwo.core (into-array String [])))

(defn -start [this primaryStage]
  (let [loc (clojure.java.io/resource "fxml_example.fxml")
        root (.load FXMLLoader ^java.net.URL loc)
        scene (Scene. root 300 250)]
    (.setScene primaryStage scene)
    (.show primaryStage)))

...我得到Caused by: java.lang.IllegalArgumentException: No matching method found: load for class java.lang.Class

所以我在FXMLLoader之后放了一个点来创建一个实例:(FXMLLoader.)我得到了这个:ClassCastException java.net.URL cannot be cast to java.io.InputStream

所以这告诉我,因为FXMLLoader的load方法之一支持InputStream,所以我正在研究。我尝试强制编译器知道资源是java.net.URL,因为这是FXMLLoader.load支持的重载之一,通过直接调用(clojure.java.io/resource...)来调用(.load...)但它仍然不喜欢它(我知道这是一个长镜头)。我也尝试了类型提示,(.load (FXMLLoader.) ^java.net.URL loc)(.load (FXMLLoader.) #^java.net.URL loc),但没有骰子;它仍然试图使用load的java.io.InputStream版本。

在java中还有getClass()调用,我认为它正在获取Application的超类,但是我不知道如何在clojure-land中使用它。

有关如何加载fxml文件的任何想法?

之后,java代码具有@FXML注释,允许FXML成为私有类成员。在clojure中这是必要的(当我删除它时java代码中断)? @Override注释似乎没有在clojure中使用。

感谢

2 个答案:

答案 0 :(得分:1)

鉴于Java语法,此处调用的load方法似乎是FXMLLoader类的静态方法。要在Clojure中调用静态方法,您需要使用(ClassName/methodName args...)语法:

(FXMLLoader/load ...)

(刚刚检查过:FXMLLoader包含带有多个签名的静态和实例load方法。您需要调用Java代码所使用的相同方法;将使用{{调用静态方法1}} Java中的语法,实例方法 - FXMLLoader.load。)

对于someFXMLLoaderInstance.load方法调用,它的目标在Java中是隐式getClass;在Clojure中,你必须使目标明确(this)。

答案 1 :(得分:1)

我能够通过创建FXMLLoader与设置位置分开来解决我的问题。

(defn -start [this primaryStage]
  (let [loc (clojure.java.io/resource "fxml_example.fxml")
        fxmlloader (FXMLLoader.)]
    (.setLocation fxmlloader loc) 
    (let [root (.load fxmlloader )
          scene (Scene. root 300 250)]
      (.setScene primaryStage scene)
      (.show primaryStage))))