Charts JavaFX图表-类别调整问题

Charts JavaFX图表-类别调整问题,charts,javafx-8,Charts,Javafx 8,我有一个用户可调整大小的图表。当图表变小时,类别轴将旋转,您将无法再看到大多数类别标签。下面是显示问题的gif: 有没有办法阻止标签旋转 我知道我可以将侦听器添加到rotation属性,并在旋转更改时将其旋转回0。但是,当我这样做时,它不会阻止间距的调整,因此标签只是被切断(您只看到标签的最后几个字符) 以下是包含的gif的代码,在调整窗口大小时,您会看到问题: import javafx.application.Application; import javafx.scene.Scene;

我有一个用户可调整大小的图表。当图表变小时,类别轴将旋转,您将无法再看到大多数类别标签。下面是显示问题的gif:

有没有办法阻止标签旋转

我知道我可以将侦听器添加到rotation属性,并在旋转更改时将其旋转回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);
    }
}
导入javafx.application.application;
导入javafx.scene.scene;
导入javafx.scene.chart.BarChart;
导入javafx.scene.chart.CategoryAxis;
导入javafx.scene.chart.NumberAxis;
导入javafx.scene.chart.XYChart;
导入javafx.stage.stage;
公共类HorizontalBarExample扩展了应用程序{
@凌驾
公众假期开始(阶段){
NumberAxis xAxis=新NumberAxis();
CategoryAxis yAxis=新CategoryAxis();
条形图bc=新条形图(xAxis,yAxis);
公元前30年挫折(0d);
bc.setCategoryGap(0);
xAxis.setticklabel旋转(90);
yAxis.ticklableRotationProperty().set(0d);
XYChart.Series系列1=新的XYChart.Series();
系列1.集合名(“示例”);
对于(int i=0;i<10;i++)
series1.getData().add(新的XYChart.Data(Math.random()*5000,“长数据标签号”+i));
bc.getData().add(series1);
场景=新场景(bc,800600);
舞台场景;
stage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}

这个问题不容易解决(IMO)

发生什么事了

Java 8u60的CategoryAxis代码在内部维护一个私有
有效的TickLabelRotation
成员。由于内部实现的原因,此成员有时可以覆盖为公共可用的
tickLabelRotationProperty
设置的任何值。因此,您对功能没有太多控制权

使用公共API修复它的各种尝试(失败)

它覆盖的一种方式是将类别轴设置为自动范围时,因此可以将自动范围设置为false,还可以使用
CategoryAxis::setCategory
方法手动设置类别。这种方法解决了这个问题,因为当图形变小时,不会使用effectiveRotation,它尊重您想要的旋转,并且文本保持垂直

然而,即使关闭自动测距和手动设置类别,在实现过程中也存在其他问题,从而无法获得合理的结果。CategoryAxis的内部布局算法仍然认为类别标签已经旋转,因此当图表变小时,它没有为标签分配足够的空间。CategoryAxis类是final类,因此不能在子类中重写布局逻辑。快速破解将设置轴的最小宽度,
yAxis.setMinWidth(200)。不幸的是,CategoryAxis布局算法也不考虑最小宽度设置

获取此功能的选项

简言之,它都坏了。。。你可以:

  • 按原样接受默认行为,或
  • 您请求修复,或
  • 将CategoryAxis代码复制到一个新类,例如HorizontallyLabelledCategoryAxis,进行一些修改以允许布局算法按您的意愿工作,并使用该新类代替原始CategoryAxis 选项3有点棘手,但可行

    建议的解决办法

    综上所述,如果你的UI可以接受的话,我推荐的方法(例如,变通)就是不要让图表变得太小,以至于布局出错

    VBox chartHolder = new VBox(bc);
    VBox.setVgrow(bc, Priority.ALWAYS);
    bc.setMinHeight(300);
    Scene scene = new Scene(chartHolder, 800, 600);
    

    我想说,这是一个bug:如果空间变小,水平显示所有标签,那么无论类别轴应该做什么,旋转都不是可行的选项之一(忽略每个n'th可能是或不是,或者在鼠标悬停在类别上,然后只显示该类别之前不显示任何n'th)