【问题标题】:JavaFX LineChart - ClassCastException because of the Axis' TypeJavaFX LineChart - ClassCastException 因为轴的类型
【发布时间】:2014-01-22 13:05:25
【问题描述】:

如何从 FXML 文件中指定图表的轴类型?似乎默认类型是<String, Integer>。如果我将我的可注入字段声明为LineChart<Number, Number> lineChart,并且我使用(Number, Number 创建了一个数据系列,程序将抛出一个ClassCastException

必须使用 FXML 文件。最坏的情况是我手动创建了图表。我最好的猜测是这是一个错误。


import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.AnchorPane;

/**
 * 
 * @author ggrec
 *
 */
public class TestChart implements Initializable
{

    // ====================== 2. Instance Fields =============================

    @FXML
    private LineChart<Number, Number> testChart;

    private AnchorPane anchorPane;


    // ==================== 4. Constructors ====================

    public TestChart()
    {
        final FXMLLoader fxmlLoader = new FXMLLoader( TestChart.class.getResource("testChart.fxml") );
        fxmlLoader.setController(this);

        try
        {
            anchorPane = (AnchorPane) fxmlLoader.load();
        }
        catch (final IOException e)
        {
            e.printStackTrace();
        }
    }


    // ==================== 5. Creators ====================

    @Override
    public void initialize(final URL arg0, final ResourceBundle arg1)
    {
        //      testChart.getXAxis().setAutoRanging(true);
        //      testChart.getYAxis().setAutoRanging(true);

        testChart.getData().add(getDummyData());
    }


    // ==================== 7. Getters & Setters ====================

    public AnchorPane getAnchorPane()
    {
        return anchorPane;
    }


    // ==================== 13. Utility Methods ====================

    private XYChart.Series getDummyData()
    {
        final XYChart.Series series = new XYChart.Series();
        series.setName("My portfolio");

        series.getData().add(new XYChart.Data<Number, Number>(1, 23)); // Works for ("1", 23)
        //      series.getData().add(new XYChart.Data("2", 14));
        //      series.getData().add(new XYChart.Data("3", 15));
        //      series.getData().add(new XYChart.Data("4", 24));
        //      series.getData().add(new XYChart.Data("5", 34));
        //      series.getData().add(new XYChart.Data("6", 36));
        //      series.getData().add(new XYChart.Data("7", 22));
        //      series.getData().add(new XYChart.Data("8", 45));
        //      series.getData().add(new XYChart.Data("9", 43));
        //      series.getData().add(new XYChart.Data("10", 17));
        //      series.getData().add(new XYChart.Data("11", 29));
        //      series.getData().add(new XYChart.Data("12", 25));

        return series;
    }
}

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at javafx.scene.chart.CategoryAxis.invalidateRange(CategoryAxis.java:399)
at javafx.scene.chart.XYChart.updateAxisRange(XYChart.java:603)
at javafx.scene.chart.XYChart.layoutChartChildren(XYChart.java:620)
at javafx.scene.chart.Chart$1.layoutChildren(Chart.java:84)
at javafx.scene.Parent.layout(Parent.java:1018)

【问题讨论】:

  • 您找到解决问题的方法了吗?因为我正在为这个问题而苦恼。
  • 你能展示 FXML 吗?

标签: java javafx


【解决方案1】:

这对我来说很好。我使用以下 FXML 进行了测试:

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

<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.chart.LineChart?>
<?import javafx.scene.chart.NumberAxis?>

<AnchorPane xmlns:fx="http://javafx.com/fxml">
    <LineChart fx:id="testChart">
    <xAxis><NumberAxis /></xAxis>
    <yAxis><NumberAxis /></yAxis>
    </LineChart>
</AnchorPane>

和测试应用程序:

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

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            TestChart chart = new TestChart();
            Scene scene = new Scene(chart.getAnchorPane(), 600, 400);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

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

如果没有看到您的 FXML 文件(尤其是您正在使用的轴),很难说出为什么您会得到 ClassCastException。但是,从堆栈跟踪来看,您使用的似乎是 CategoryAxis,它与 LineChart&lt;Number, Number&gt; 的类型不兼容。

通常,您可以将两种数据类型(一种用于 x,一种用于 y)声明为您想要的任何类型。既然你已经声明了

@FXML
private LineChart<Number, Number> testChart ;

x 变量的类型和 y 变量的类型都是Number

参考Javadocs for LineChartLineChart&lt;X,Y&gt; 需要 Axis&lt;X&gt; 用于 x 轴,Axis&lt;Y&gt; 用于 y 轴。所以每个轴都需要一个Axis&lt;Number&gt;CategoryAxisAxis&lt;String&gt;(同样,请参阅 Javadocs),因此它不能用作折线图的轴:轴的数据类型与图表的数据类型不兼容。

如果您在 Java 中尝试过以下操作:

LineChart<Number, Number> testChart ;
testChart = new LineChart<>(new CategoryAxis(), new NumberAxis());

你会得到一个编译错误。由于您(可能)在 FXML 中初始化轴,并且 FXML 没有类型检查,因此您会在运行时获得 ClassCastException

对您的代码有帮助的一件事是使用正确键入的Series

private XYChart.Series<Number, Number> getDummyData()
{
    final XYChart.Series<Number, Number> series = new XYChart.Series<>();
    series.setName("My portfolio");
    // ...
}

现在编译器将检查Series 的类型是否与图表的类型相匹配,以及Data 的类型是否与Series 的类型相匹配。 (所以series.getData().add(new XYChart.Data("1", 23)); 会给出编译错误,而不是运行时错误。)由于您在 FXML 中创建轴,您仍然没有对这些轴进行类型检查,但我认为错误的原因(也许)会变得更清楚。

解决方法是使用NumberAxis,如我上面的示例所示,而不是您的CategoryAxis。如果你真的想使用CategoryAxis 作为x 轴,x 值必须是Strings,所以你需要将LineChart 声明为LineChart&lt;String, Number&gt;。同样,您可以将Series 设为Series&lt;String, Number&gt;

【讨论】:

  • 你好詹姆斯。您在这里使用什么 JavaFX 版本?另外,您是否尝试过所有这些组合:数字-数字、字符串-数字、数字-字符串、字符串-字符串?
  • JDK 1.8.0_11。也许我不明白这个问题。由于您将LineChart 声明为LineChart&lt;Number, Number&gt;,您只能希望添加x 和y 均为Numbers 的数据,因此尝试传入String 值是没有意义的。或者你正在尝试做其他事情?你用的是什么轴?
  • @James_D 也许他想问你关于创建轴的问题,而不是在 fxml 上定义它们。在某些情况下,我们可能会构建一个具有动态轴的图表,因此必须在应用程序端定义它,然后将其参数传递给 fxml。
  • 没有办法做到这一点。 LineChart 构造函数都采用轴的参数,并且这些轴是不可变的。因此,在创建图表时,必须指定轴。轴的类型必须与图表的相应类型相匹配。因此,如果您使用CategoryAxis(即Axis&lt;String&gt;)作为x 轴,则必须有某种XYChart&lt;String, Something&gt;(例如LineChart&lt;String, Number&gt;
  • @James_D 虽然我前一段时间没有处理这个问题,但我很感激你的努力。
猜你喜欢
  • 1970-01-01
  • 2014-08-14
  • 2012-10-15
  • 1970-01-01
  • 2013-04-05
  • 1970-01-01
  • 1970-01-01
  • 2017-06-16
  • 2018-05-12
相关资源
最近更新 更多