我有一个用户可调整大小的图表。当图表变小时,CategoryAxis 会旋转,您将无法再看到大多数类别标签。这是显示问题的 gif:
有什么办法可以阻止标签旋转吗?
我知道我可以向旋转属性添加一个侦听器,并在旋转发生变化时将其旋转回 0。但是,当我这样做时,它不会阻止间距调整,因此标签会被切断(您只能看到标签的最后几个字符)。
这是包含的 gif 的代码,当您调整窗口大小时您会看到问题:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
这个问题不容易解决(IMO)。
这是怎么回事
Java 8u60 的 CategoryAxis 代码在内部维护一个私有effectiveTickLabelRotation成员。由于内部实现,该成员有时可以覆盖您为公开可用的设置的任何值tickLabelRotationProperty。所以你实际上对功能没有太多控制权。
使用公共 API 进行各种(失败的)修复尝试
它覆盖的一种方法是将类别轴设置为 autoRanging,因此您可以将 autoRanging 设置为 false,也可以使用该CategoryAxis::setCategory方法手动设置类别。这样可以解决问题,因为当图形变小时,不会使用 effectiveRotation,它会尊重您想要的旋转并且文本保持垂直。
然而,即使关闭自动量程并手动设置类别,实施中仍存在其他怪癖,无法获得合理的结果。CategoryAxis 的内部布局算法仍然认为类别标签已旋转,因此当图表变小时,它不会为标签分配足够的空间。CategoryAxis 类是最终类,因此布局逻辑不能在子类中重写。一个快速技巧是设置轴的最小宽度yAxis.setMinWidth(200);。不幸的是,CategoryAxis 布局算法也不尊重最小宽度设置。
获得此功能的选项
简而言之,一切都被破坏了......你要么:
选项 3 有点棘手,但可行。
建议的解决方法
话虽如此,如果您的 UI 可以接受,我建议的方法(例如解决方法)就是不要让图表变得足够小而导致其布局混乱。
VBox chartHolder = new VBox(bc);
VBox.setVgrow(bc, Priority.ALWAYS);
bc.setMinHeight(300);
Scene scene = new Scene(chartHolder, 800, 600);
Run Code Online (Sandbox Code Playgroud)