JavaFX:自定义ScatterChart

时间:2016-06-23 16:30:41

标签: javafx-8

我正在尝试自定义javafx控件,我在使用ScatterChart时遇到了一些问题。 我想要做的是扩展标准ScatterChart,以便我可以添加一个属性,我稍后将绑定到ImageView的视口。 在开始绑定之前(这对我来说也是新的)我尝试了一个最小的实现,看看我是否把事情做对了。这是自定义BindableChart

的代码
<property environment="env"/>

这里是它的fxml代码

public class BindableChart<X,Y> extends ScatterChart<X,Y>
    public BindableChart(@NamedArg("xAxis")Axis<X> xAxis,@NamedArg("yAxis")Axis<Y> yAxis){
        super(xAxis,yAxis);
        FXMLLoader fxmlLoader = new FXMLLoader(
        getClass().getResource("/fxml/BindableChart.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }
}

当我尝试运行包含BindableChart类的测试应用程序时,我得到一个PropertyNotFoundException,表示xAxis属性不存在或是只读的。 有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您尝试定义轴两次:一次在FXML文件中,一次在Java代码中。请注意,当您在FXML加载程序上调用load()时(即解析FXML文件时),已经通过调用超类构造函数来定义轴。

如果你要继承ScatterChart,那么你几乎必须通过Java代码初始化轴。如果要强制轴为NumberAxis的实例,则可以通过在super()的调用中创建它们来实现。当然,NumberAxis是子类Axis<Number>,因此强制BindableChart成为ScatterChart<Number, Number>的子类,因此您最终会使用

package bindablechart ;

import java.io.IOException;

import javafx.fxml.FXMLLoader;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.ScatterChart;

public class BindableChart extends ScatterChart<Number, Number> {
    public BindableChart(){
        super(new NumberAxis(), new NumberAxis());
        FXMLLoader fxmlLoader = new FXMLLoader(
                getClass().getResource("BindableChart.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }
}

并且FXML变为

<?xml version="1.0" encoding="UTF-8"?>

<fx:root xmlns:fx="http://javafx.com/fxml/1" type="bindablechart.BindableChart">

</fx:root>

(此时,FXML可能会变得完全多余;我不知道你还有什么,如果有的话。)

此版本的测试如下:

package bindablechart;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class BindableChartTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        Scene scene = new Scene(new BindableChart());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

或者您可以使用

将其包含在另一个FXML文件中
<BindingChart />

如果你想让这个类的用户指定轴,你可以这样做,但你仍然可以从FXML中删除它们(因为用户指定了它们)......:

package bindablechart;
import java.io.IOException;

import javafx.beans.NamedArg;
import javafx.fxml.FXMLLoader;
import javafx.scene.chart.Axis;
import javafx.scene.chart.ScatterChart;

public class BindableChart<X,Y> extends ScatterChart<X, Y> {
    public BindableChart(@NamedArg("xAxis") Axis<X> xAxis, @NamedArg("yAxis") Axis<Y> yAxis){
        super(xAxis, yAxis);
        FXMLLoader fxmlLoader = new FXMLLoader(
                getClass().getResource("BindableChart.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }
}

使用与上述相同的FXML文件。

在这种情况下,测试用例看起来像

package bindablechart;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.stage.Stage;

public class BindableChartTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        Scene scene = new Scene(
            new BindableChart<Number, Number>(new NumberAxis(), new NumberAxis()));
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

或者您可以使用

在FXML中创建一个
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.chart.NumberAxis?>
<?import bindablechart.BindableChart?>

<StackPane xmlns:fx="http://javafx.com/fxml/1">
    <BindableChart>
        <xAxis><NumberAxis/></xAxis>
        <yAxis><NumberAxis/></yAxis>
    </BindableChart>
</StackPane>