尝试在折线图中将日期放在Xaxis上时出错

时间:2016-08-29 09:48:50

标签: java javafx linechart

package org.gillius.jfxutils.examples;

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.gillius.jfxutils.JFXUtil;
import org.gillius.jfxutils.chart.ChartPanManager;
import org.gillius.jfxutils.chart.FixedFormatTickFormatter;
import org.gillius.jfxutils.chart.JFXChartUtil;
import org.gillius.jfxutils.chart.StableTicksAxis;

import java.text.SimpleDateFormat;
import java.util.TimeZone;

public class Test extends Application {
    public static void main( String[] args ) {
        launch( args );
    }

    @FXML
    private LineChart<Number, Number> chart;

    @FXML
    private Slider valueSlider;

    @FXML
    private Label outputLabel;

    private XYChart.Series<Number, Number> series;

    private long startTime;

    private Timeline addDataTimeline;

    @FXML
    void addSample() {
        series.getData().add(new XYChart.Data(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));
    }
@FXML
    void autoZoom() {
        chart.getXAxis().setAutoRanging( true );
        chart.getYAxis().setAutoRanging( true );
    }

    @FXML
    void toggleAdd() {
        switch ( addDataTimeline.getStatus() ) {
            case PAUSED:
            case STOPPED:
                addDataTimeline.play();
                chart.getXAxis().setAutoRanging( true );
                chart.getYAxis().setAutoRanging( true );
                //Animation looks horrible if we're updating a lot
                chart.setAnimated( false );
                chart.getXAxis().setAnimated( false );
                chart.getYAxis().setAnimated( false );
                break;
            case RUNNING:
addDataTimeline.stop();
                //Return the animation since we're not updating a lot
                chart.setAnimated( true );
                chart.getXAxis().setAnimated( true );
                chart.getYAxis().setAnimated( true );
                break;

            default:
                throw new AssertionError( "Unknown status" );
        }
    }

    @Override
    public void start( Stage stage ) throws Exception {
        FXMLLoader loader = new FXMLLoader( getClass().getResource( "Charting.fxml" ) );
        Region contentRootRegion = (Region) loader.load();

        StackPane root = JFXUtil.createScalePane( contentRootRegion, 960, 540, false );
        Scene scene = new Scene( root, root.getPrefWidth(), root.getPrefHeight() );
        stage.setScene( scene );
        stage.setTitle( "Charting Example" );
        stage.show();
}

@FXML
    void initialize() {
        startTime = System.currentTimeMillis();

        //Set chart to format dates on the X axis
//      SimpleDateFormat format = new SimpleDateFormat( "HH:mm:ss" );
//      format.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
//      ((StableTicksAxis) chart.getXAxis()).setAxisTickFormatter(
//              new FixedFormatTickFormatter( format ) );

        series = new XYChart.Series<Number, Number>();
        series.setName( "Data" );

        chart.getData().add( series );

        addDataTimeline = new Timeline( new KeyFrame(
                Duration.millis( 250 ),
                new EventHandler<ActionEvent>() {
                    @Override
                    public void handle( ActionEvent actionEvent ) {
                        addSample();
                    }
                }
        ));
        addDataTimeline.setCycleCount( Animation.INDEFINITE );

        chart.setOnMouseMoved( new EventHandler<MouseEvent>() {
            @Override
            public void handle( MouseEvent mouseEvent ) {
                double xStart = chart.getXAxis().getLocalToParentTransform().getTx();
                double axisXRelativeMousePosition = mouseEvent.getX() - xStart;

            }
        } );

//Panning works via either secondary (right) mouse or primary with ctrl held down
        ChartPanManager panner = new ChartPanManager( chart );
        panner.setMouseFilter( new EventHandler<MouseEvent>() {
            @Override
            public void handle( MouseEvent mouseEvent ) {
                if ( mouseEvent.getButton() == MouseButton.SECONDARY ||
                         ( mouseEvent.getButton() == MouseButton.PRIMARY &&
                           mouseEvent.isShortcutDown() ) ) {
                    //let it through
                } else {
                    mouseEvent.consume();
                }
            }
        } );
        panner.start();

        //Zooming works only via primary mouse button without ctrl held down
        JFXChartUtil.setupZooming( chart, new EventHandler<MouseEvent>() {
            @Override
            public void handle( MouseEvent mouseEvent ) {
                if ( mouseEvent.getButton() != MouseButton.PRIMARY ||
                     mouseEvent.isShortcutDown() )
                    mouseEvent.consume();
            }
        } );

        JFXChartUtil.addDoublePrimaryClickAutoRangeHandler( chart );
    }
}

这是我的折线图代码。它一直运行良好,直到我尝试在Xaxis上插入一个字符串。我希望有这个图表,但在Xaxis上有字符串。我收到了这个错误: javafx.scene.chart.CategoryAxis无法强制转换为javafx.scene.chart.ValueAxis

1 个答案:

答案 0 :(得分:0)

问题在于您将图表定义为LineChart<Number, Number>

要制作包含String X值和Number Y值的图表,您应将通用参数设置为:

LineChart<String, Number> chart;

然后很可能你想使用CategoryAxis

  

一个轴实现,适用于每个字符串类别   值作为沿轴的唯一类别(刻度线)。

注意:由于图表来自FXML文件,您还必须更新FXML文件。

示例

CategoryAxis xAxis = new CategoryAxis();
NumberAxis yAxis = new NumberAxis();       

LineChart<String,Number> chart = new LineChart<String,Number>(xAxis,yAxis);

此外,您还必须更新系列的声明和初始化:

private XYChart.Series<String, Number> series;
...
series = new XYChart.Series<String, Number>();

然后您可以将数据添加到此系列中:

series.getData().add(new XYChart.Data("SomeString", 23));

您可以查看原始教程的Creating Categories for a Line Chart section (example 3-4)

<强>更新

它发现JFXUtils package used仅在ValueAxis的情况下不支持zomming。一种可能的解决方案是为条形图创建缩放,如this answer中建议的那样。