Can I keep integral tick marks even with autoranging on an Axis?

核能气质少年 提交于 2019-12-10 16:48:22

问题


I "stole" some code from here to have an AreaChart with "smooth lines" which I use in my FXML and it works:

    <SmoothedAreaChart fx:id="chart" legendVisible="false"
        title="Tree depth by line" animated="false">
        <xAxis>
            <NumberAxis fx:id="xAxis" tickUnit="1.0" autoRanging="false"
                minorTickVisible="false" forceZeroInRange="false"
                label="Line number"/>
        </xAxis>
        <yAxis>
            <NumberAxis fx:id="yAxis" minorTickVisible="false"
                tickUnit="1.0" forceZeroInRange="true" label="Tree depth"/>
        </yAxis>
    </SmoothedAreaChart>

The problem I have however is with the Y axis.

I set the tickUnit to 1.0 because I want, well, integral units, but it doesn't quite work:

If, in the definition of yAxis, I set autoRanging to false then the graph is cropped (I set the upper bound by hand when I fill the graph):

And, well, there are too many tick marks as well.

Basically, I'd like the behavior of both:

  • that the autoranging takes place,
  • but that the tick marks always be integral numbers.

Is there a possibility to do this, or do I need to code my own/find an implementation of Axis which does that?


回答1:


OK, well, I found a solution, sort of.

I don't specify the tick unit in the FXML anymore; instead I do this in the code where I also set the maximum value of the y axis (and autoranging is set to false):

display.yAxis.setUpperBound(maxDepth);
final int tickUnit = maxDepth / 15;
display.yAxis.setTickUnit(Math.max(tickUnit, 1));

That's kind of a hack, of course, and I sure wish it were in the API to start with. Or maybe it is and I didn't see it...




回答2:


Here you can see just a few lines to format the numbers however you want. (SO overlords asked for an explanation)

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;

public class AxisFormatter extends Application {
    final NumberAxis xAxis = new NumberAxis();
    final NumberAxis yAxis = new NumberAxis();
    final LineChart<Number, Number> chart = new LineChart<>(xAxis, yAxis);
    double i = 0d;

    final StringConverter<Number> converter =  new StringConverter<Number>() {
        @Override public String toString(Number object) {
            //just an untested idea for isInteger
            return object.doubleValue() == object.intValue() 
                    ? object.intValue()+""
                    :"";
        }
        @Override public Number fromString(String string) { return 0;}
    };

    @Override public void start(Stage primaryStage) {

        chart.getData().add(new XYChart.Series<>());

        while (i++ < 10d)
            chart.getData().get(0).getData().add(new XYChart.Data<>(i,i/2));

        Button btn1 = new Button("increase max y value");
        btn1.setOnAction((evt)->{
            chart.getData().get(0).getData().add(new XYChart.Data<>(i++,i/2));
        });

        Button btn2 = new Button("change formatter");
        btn2.setOnAction((evt)->{
            yAxis.setTickLabelFormatter(yAxis.getTickLabelFormatter() == converter
                ? null : converter);
        });

        yAxis.setTickLabelFormatter(converter);

        VBox root = new VBox(chart, new HBox(5,btn1,btn2));
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

}


来源:https://stackoverflow.com/questions/28396952/can-i-keep-integral-tick-marks-even-with-autoranging-on-an-axis

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!