JavaFX中的象限散点图?

JavaFX中的象限散点图?,java,charts,javafx-8,scatter,Java,Charts,Javafx 8,Scatter,谢谢你阅读我的问题 我目前正在使用JavaFX-8、SceneBuilder和Eclipse 我想做一个有四个象限的散点图,有两个固定的数字轴(数据位置不相关,我只需要显示每个象限上的点…只关心点在哪个象限)。每个象限必须有特定颜色的背景 我找到了,所以我尝试扩展散点图,目的是覆盖layoutPlotChildren()方法。我尝试了一个最低限度的实现,看看它是否会与我的FXML一起运行(我确实将新组件导入了FXML)。这是我的最低执行: public class ScatterQuadrant

谢谢你阅读我的问题

我目前正在使用JavaFX-8、SceneBuilder和Eclipse

我想做一个有四个象限的散点图,有两个固定的数字轴(数据位置不相关,我只需要显示每个象限上的点…只关心点在哪个象限)。每个象限必须有特定颜色的背景

我找到了,所以我尝试扩展散点图,目的是覆盖layoutPlotChildren()方法。我尝试了一个最低限度的实现,看看它是否会与我的FXML一起运行(我确实将新组件导入了FXML)。这是我的最低执行:

public class ScatterQuadrantChart<X,Y> extends ScatterChart<X,Y> {
  public ScatterQuadrantChart(Axis<X> xAxis, Axis<Y> yAxis) {
      super(xAxis, yAxis);
} }
公共类散点象限图扩展散点图{
公共散射象限图(X轴、Y轴){
超级(xAxis,yAxis);
} }
然后,我得到NotSuchMethodError init错误。我发现了一个类似的错误,但是有人扩展了LineChart,但是我不太确定我自己的类需要做什么

我尝试添加一个无参数构造函数,但我需要调用super和cant,因为我也不能调用“getXAxis()”方法。我在这里该怎么办

另外,剩下的另一个问题是,一旦我解决了这个问题,layoutPlotChildren()方法应该做什么


感谢阅读。

您看到的问题之所以出现,是因为
fxmloader
实例化类的默认机制是调用无参数构造函数。您的
ScatterQuadrantChart
没有参数构造函数,因此
NoSuchMethodError

在Java8之前,解决此问题的唯一方法是为类创建一个构建器类,如您链接的帖子所示。JavaFX8引入(但未能记录)一种机制来指定构造函数参数的值,该参数将由
FXMLLoader
使用
@NamedArg
注释识别

因此,在Java 8中,您可以修改您的
散点象限图

public class ScatterQuadrantChart<X,Y> extends ScatterChart<X,Y> {
  public ScatterQuadrantChart(@NamedArg("xAxis")Axis<X> xAxis, 
         @NamedArg("yAxis)Axis<Y> yAxis) {
      super(xAxis, yAxis);
  } 
}
测试代码:

import java.util.Random;
import java.util.stream.Stream;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class ScatterQuadrantChartTest extends Application {

    @Override
    public void start(Stage primaryStage) {

        final Random rng = new Random();

        ScatterQuadrantChart<Number, Number> chart = new ScatterQuadrantChart<>(new NumberAxis(), new NumberAxis());
        Series<Number, Number> series = new Series<>();
        for (int i=0; i<20; i++) {
            series.getData().add(new Data<>(rng.nextDouble() * 100, rng.nextDouble() * 100));
        }
        chart.getData().add(series);

        chart.setXQuadrantDivider(50);
        chart.setYQuadrantDivider(50);

        BorderPane root = new BorderPane(chart);
        Scene scene = new Scene(root, 600, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

}
import java.util.Random;
导入java.util.stream.stream;
导入javafx.application.application;
导入javafx.scene.scene;
导入javafx.scene.chart.NumberAxis;
导入javafx.scene.chart.XYChart.Data;
导入javafx.scene.chart.XYChart.Series;
导入javafx.scene.layout.BorderPane;
导入javafx.stage.stage;
公共类散射象限图测试扩展应用{
@凌驾
公共无效开始(阶段primaryStage){
最终随机rng=新随机();
散射象限图=新的散射象限图(新的NumberAxis(),新的NumberAxis());
系列=新系列();

对于(int i=0;i谢谢你@James_D!FXML工作正常,它可以完美地加载,没有错误。我现在的问题是第二个问题:“如何实现”layoutPlotChildren"要绘制彩色背景?使用示例实现更新了答案。再次感谢@James_D!我尝试了代码,但象限不可见。我在设置样式类之前尝试了代码,并删除了更改点形状以避免问题的CSS。但是,区域不可见。我尝试替换了列用于十六进制代码的OR,但它们仍然是透明的。请确保您设置了
xQuadrantDivider
yQuadrantDivider
值。我用测试代码进行了更新。它的工作方式很有魅力!!将对其进行调整以适应样式,谢谢!!:D
import javafx.beans.NamedArg;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.scene.chart.Axis;
import javafx.scene.chart.ScatterChart;
import javafx.scene.layout.Region;

public class ScatterQuadrantChart<X,Y> extends ScatterChart<X,Y> {

    private final Property<X> xQuadrantDivider = new SimpleObjectProperty<>();
    private final Property<Y> yQuadrantDivider = new SimpleObjectProperty<>();

    private final Region nwQuad ;
    private final Region neQuad ;
    private final Region swQuad ;
    private final Region seQuad ;

    public ScatterQuadrantChart(@NamedArg("xAxis") Axis<X> xAxis, 
            @NamedArg("yAxis") Axis<Y> yAxis) {
        super(xAxis, yAxis);
        nwQuad = new Region();
        neQuad = new Region();
        swQuad = new Region();
        seQuad = new Region();
        nwQuad.setStyle("-fx-background-color: lightsalmon ;");
        neQuad.setStyle("-fx-background-color: antiquewhite ;");
        swQuad.setStyle("-fx-background-color: aqua ;");
        seQuad.setStyle("-fx-background-color: lightskyblue ;");
        getPlotChildren().addAll(nwQuad, neQuad, swQuad, seQuad);

        ChangeListener<Object> quadListener = (obs, oldValue, newValue) -> layoutPlotChildren();
        xQuadrantDivider.addListener(quadListener);
        yQuadrantDivider.addListener(quadListener);
    }

    @Override
    public void layoutPlotChildren() {
        super.layoutPlotChildren();
        X x = xQuadrantDivider.getValue();
        Y y = yQuadrantDivider.getValue();
        if (x != null && y != null) {
            Axis<X> xAxis = getXAxis();
            Axis<Y> yAxis = getYAxis();
            double xPixels = xAxis.getDisplayPosition(x);
            double yPixels = yAxis.getDisplayPosition(y);
            double totalWidth = xAxis.getWidth();
            double totalHeight = yAxis.getHeight();
            nwQuad.resizeRelocate(0, 0, xPixels, yPixels);
            swQuad.resizeRelocate(0, yPixels, xPixels, totalHeight - yPixels);
            neQuad.resizeRelocate(xPixels, 0, totalWidth - xPixels, yPixels);
            seQuad.resizeRelocate(xPixels, yPixels, totalWidth - xPixels, totalHeight - yPixels);
        }
    }

    public final Property<X> xQuadrantDividerProperty() {
        return this.xQuadrantDivider;
    }

    public final X getXQuadrantDivider() {
        return this.xQuadrantDividerProperty().getValue();
    }

    public final void setXQuadrantDivider(final X xQuadrantDivider) {
        this.xQuadrantDividerProperty().setValue(xQuadrantDivider);
    }

    public final Property<Y> yQuadrantDividerProperty() {
        return this.yQuadrantDivider;
    }

    public final Y getYQuadrantDivider() {
        return this.yQuadrantDividerProperty().getValue();
    }

    public final void setYQuadrantDivider(final Y yQuadrantDivider) {
        this.yQuadrantDividerProperty().setValue(yQuadrantDivider);
    }


}
import java.util.Random;
import java.util.stream.Stream;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class ScatterQuadrantChartTest extends Application {

    @Override
    public void start(Stage primaryStage) {

        final Random rng = new Random();

        ScatterQuadrantChart<Number, Number> chart = new ScatterQuadrantChart<>(new NumberAxis(), new NumberAxis());
        Series<Number, Number> series = new Series<>();
        for (int i=0; i<20; i++) {
            series.getData().add(new Data<>(rng.nextDouble() * 100, rng.nextDouble() * 100));
        }
        chart.getData().add(series);

        chart.setXQuadrantDivider(50);
        chart.setYQuadrantDivider(50);

        BorderPane root = new BorderPane(chart);
        Scene scene = new Scene(root, 600, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

}