JavaFX LineChart – 由于Axis的类型而导致ClassCastException

如何从FXML文件中指定图表的轴类型? 看起来默认类型是 。 如果我将我的可注入字段声明为LineChart 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 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(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:

           

和测试应用程序:

 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不是类型兼容的。

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

 @FXML private LineChart testChart ; 

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

参考LineChart的Javadocs , LineChart要求x轴为Axis ,y轴为Axis 。 因此,每个轴需要一个AxisCategoryAxisAxis (同样,请参考Javadocs ),因此它不能用作折线图的轴:轴的数据类型与图表的数据类型不兼容。

如果您在Java中尝试了以下内容:

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

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

有助于您的代码的一件事是使用正确类型的Series

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

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

修复是使用NumberAxis ,如上例所示,而不是CategoryAxis 。 如果你真的想在X轴上使用CategoryAxis ,那么x值必须是String s,因此你需要将LineChart声明为LineChart 。 类似地,你可以使Series a Series