问题
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