设置条形图列宽度大小

Pet*_*zov 4 javafx javafx-2 javafx-8

有没有办法设置JavaFX条形图列宽度大小?

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 BarChartSample extends Application {
    final static String austria = "Austria";
    final static String brazil = "Brazil";
    final static String france = "France";
    final static String italy = "Italy";
    final static String usa = "USA";

    @Override public void start(Stage stage) {
        stage.setTitle("Bar Chart Sample");
        final CategoryAxis xAxis = new CategoryAxis();
        final NumberAxis yAxis = new NumberAxis();
        final BarChart<String,Number> bc = 
            new BarChart<String,Number>(xAxis,yAxis);
        bc.setTitle("Country Summary");
        xAxis.setLabel("Country");       
        yAxis.setLabel("Value");

        XYChart.Series series1 = new XYChart.Series();
        series1.setName("2003");       
        series1.getData().add(new XYChart.Data(austria, 25601.34));
        series1.getData().add(new XYChart.Data(brazil, 20148.82));
        series1.getData().add(new XYChart.Data(france, 10000));
        series1.getData().add(new XYChart.Data(italy, 35407.15));
        series1.getData().add(new XYChart.Data(usa, 12000));      

        XYChart.Series series2 = new XYChart.Series();
        series2.setName("2004");
        series2.getData().add(new XYChart.Data(austria, 57401.85));
        series2.getData().add(new XYChart.Data(brazil, 41941.19));
        series2.getData().add(new XYChart.Data(france, 45263.37));
        series2.getData().add(new XYChart.Data(italy, 117320.16));
        series2.getData().add(new XYChart.Data(usa, 14845.27));  

        XYChart.Series series3 = new XYChart.Series();
        series3.setName("2005");
        series3.getData().add(new XYChart.Data(austria, 45000.65));
        series3.getData().add(new XYChart.Data(brazil, 44835.76));
        series3.getData().add(new XYChart.Data(france, 18722.18));
        series3.getData().add(new XYChart.Data(italy, 17557.31));
        series3.getData().add(new XYChart.Data(usa, 92633.68));  

        Scene scene  = new Scene(bc,800,600);
        bc.getData().addAll(series1, series2, series3);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

例如,有一种setBarGap大小的方法,但我找不到设置条形图列的最大宽度的方法.

有办法解决这个问题吗?

Jos*_*eda 5

BarChart基于两者barGap(同一类别中的categoryGap条之间的间隙)和(单独类别中的条之间的间隙)可以由用户设置,因此对于给定尺寸的图表,每次在内部计算条的宽度请求布局.

要在每个条上设置最大宽度,我们必须更改barGapcategoryGap相应地更改.但我们可以通过编程方式进行,以响应图表宽度的任何变化.

我们首先计算初始布局的条宽.根据BarChart.layoutPlotChildren():

double catSpace = xAxis.getCategorySpacing();
double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getBarGap());
double barWidth = (avilableBarSpace / bc.getData().size()) - bc.getBarGap();
Run Code Online (Sandbox Code Playgroud)

在OP提供的示例中,给定默认间隙值(barGap=4,categoryGap=10),结果barWidth为37.4.

假设我们要设置限制为40,最小类别间隔为10:

double maxBarWidth=40;
double minCategoryGap=10;
Run Code Online (Sandbox Code Playgroud)

如果在调整场景大小时图表的宽度增加,我们可以barWidth通过增加来限制categoryGap:

double barWidth=0;
do{
    double catSpace = xAxis.getCategorySpacing();
    double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getBarGap());
    barWidth = (avilableBarSpace / bc.getData().size()) - bc.getBarGap();
    if(barWidth > maxBarWidth){
        avilableBarSpace=(maxBarWidth + bc.getBarGap())* bc.getData().size();
        bc.setCategoryGap(catSpace-avilableBarSpace-bc.getBarGap());
    }
} while(barWidth>maxBarWidth);
Run Code Online (Sandbox Code Playgroud)

请注意do-while循环:当我们修改categoryGap新布局时,会执行一些初始值更改.通常需要两次迭代才能获得所需的结果.

只要图表的宽度不断增长,我们就可以重复此操作.

但是如果图表的宽度开始减小,则类别之间的差距也应该减小,而条形宽度保持接近其最大值:

double barWidth=0;
do{
    double catSpace = xAxis.getCategorySpacing();
    double avilableBarSpace = catSpace - (minCategoryGap + bc.getBarGap());
    barWidth = Math.min(maxBarWidth, (avilableBarSpace / bc.getData().size()) - bc.getBarGap());
    avilableBarSpace=(barWidth + bc.getBarGap())* bc.getData().size();
    bc.setCategoryGap(catSpace-avilableBarSpace-bc.getBarGap());
} while(barWidth < maxBarWidth && bc.getCategoryGap()>minCategoryGap);
Run Code Online (Sandbox Code Playgroud)

把所有东西放在一起,并听取场景宽度的变化:

    ...
    Scene scene  = new Scene(bc,800,600);
    bc.getData().addAll(series1, series2, series3);
    stage.setScene(scene);
    stage.show();

    double maxBarWidth=40;
    double minCategoryGap=10;

    scene.widthProperty().addListener((obs,n,n1)->{
        if(bc.getData().size()==0) return;

        if(n!=null && (n1.doubleValue()>n.doubleValue())){
            double barWidth=0;
            do{
                double catSpace = xAxis.getCategorySpacing();
                double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getBarGap());
                barWidth = (avilableBarSpace / bc.getData().size()) - bc.getBarGap();
                if (barWidth >maxBarWidth){
                    avilableBarSpace=(maxBarWidth + bc.getBarGap())* bc.getData().size();
                    bc.setCategoryGap(catSpace-avilableBarSpace-bc.getBarGap());
                }
            } while(barWidth>maxBarWidth);
        }

        if(n!=null && (n1.doubleValue()<n.doubleValue()) && bc.getCategoryGap()>minCategoryGap){
            double barWidth=0;
            do{
                double catSpace = xAxis.getCategorySpacing();
                double avilableBarSpace = catSpace - (minCategoryGap + bc.getBarGap());
                barWidth = Math.min(maxBarWidth, (avilableBarSpace / bc.getData().size()) - bc.getBarGap());
                avilableBarSpace=(barWidth + bc.getBarGap())* bc.getData().size();
                bc.setCategoryGap(catSpace-avilableBarSpace-bc.getBarGap());
            } while(barWidth < maxBarWidth && bc.getCategoryGap()>minCategoryGap);
        }
    });
Run Code Online (Sandbox Code Playgroud)

请注意,在其余情况下,barWidth将在内部计算.