I have a user-resizable chart. When the chart gets smaller the CategoryAxis rotates and you can no longer see most of the category labels. Here is a gif showing the problem:
Is there any way to stop the labels from rotating?
I know I can add a listener to the rotation property and rotate it back to 0 if the rotation changes. However, when I do that it doesn't prevent the spacing from adjusting, so the labels just get cut off (you only see the last few characters of the label).
Here is the code for the included gif, you'll see the problem as you resize the window:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
public class HorizontalBarExample extends Application {
@Override
public void start(Stage stage) {
NumberAxis xAxis = new NumberAxis();
CategoryAxis yAxis = new CategoryAxis();
BarChart<Number, String> bc = new BarChart<Number, String>(xAxis, yAxis);
bc.setBarGap(0d);
bc.setCategoryGap(0);
xAxis.setTickLabelRotation(90);
yAxis.tickLabelRotationProperty().set(0d);
XYChart.Series<Number, String> series1 = new XYChart.Series<>();
series1.setName("example");
for (int i = 0; i < 10; i++)
series1.getData().add(new XYChart.Data<Number, String>(Math.random() * 5000, "long data label number" + i));
bc.getData().add(series1);
Scene scene = new Scene(bc, 800, 600);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This issue is not easily fixable (IMO).
What's going on
The CategoryAxis code for Java 8u60 internally maintains a private effectiveTickLabelRotation
member. This member can at times, due to the internal implementation, override whatever value you set for the publicly available tickLabelRotationProperty
. So you don't really have much control over the functionality.
Various (failed) attempts to fix it using public API
One way that it overrides is when the the category axis is set to autoRanging, so you can set autoRanging to false and also manually set the categories using the CategoryAxis::setCategory
method. This kind of fixes the issue because then the effectiveRotation is not used when the graph gets small, it respects the rotation you want and the text stays vertical.
However, even with switching auto ranging off and manually setting categories, there are other quirks in the implementation which prevent a reasonable result. The internal layout algorithm for the CategoryAxis still thinks that the category labels have been rotated, so it does not allocate enough space for the labels when the chart gets smaller. The CategoryAxis class is final so the layout logic can't be overridden in a subclass. A quick hack would be set a minimum width for the axis, yAxis.setMinWidth(200);
. Unfortunately the CategoryAxis layout algorithm does not respect the min width setting either.
Options to get this functionality
In short, it's all kind of broken ... you either:
Option 3 is a bit tricky, but doable.
Suggested Work-around
All that said, the approach (e.g. work-around) I'd recommend, if it is acceptable for your UI, is simply not to let the chart get small enough that its layout screws up.
VBox chartHolder = new VBox(bc);
VBox.setVgrow(bc, Priority.ALWAYS);
bc.setMinHeight(300);
Scene scene = new Scene(chartHolder, 800, 600);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With