且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

限制条形图的宽度大小

更新时间:2023-01-13 17:52:36

正如我们已经讨论的那样这里,要设置每个条形的最大宽度,我们必须更改 barGap categoryGap 因此,每次调整场景或图表的大小。

As we already discussed here, to set a maximum width on every bar, we have to change either barGap or categoryGap accordingly, every time the scene or the chart are resized.

唯一的区别是提到问题,我们是否必须在第一次显示时调整图表大小。

The only difference from the refered question, is we have to resize the chart the first time is displayed.

基于相同的代码,让我们创建 setMaxBarWidth()方法:

Based on the same code, let's create the setMaxBarWidth() method:

private final NumberAxis yAxis = new NumberAxis();
private final CategoryAxis xAxis = new CategoryAxis();
private final BarChart<String,Number> bc = new BarChart<>(xAxis,yAxis);

private void setMaxBarWidth(double maxBarWidth, double minCategoryGap){
    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);

    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);
}

现在创建图片的图表,但宽度为40px:

And now create the chart of your pic, but with a width of 40px:

@Override 
public void start(Stage stage) {
    bc.setTitle("1");
    xAxis.setLabel("Groups");       
    yAxis.setLabel("Value");

    XYChart.Series series1 = new XYChart.Series();
    series1.setName("Groups");       
    series1.getData().add(new XYChart.Data("kk", 1));

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

    setMaxBarWidth(40, 10);
    bc.widthProperty().addListener((obs,b,b1)->{
        Platform.runLater(()->setMaxBarWidth(40, 10));
    });
}

编辑

I已经使用 Platform.runLater()将调用包装到 setMaxBarWidth(),因此场景图有时间刷新正确地绘制图表,在while循环期间避免多次重绘。此外,我已将监听器移至 bc.widthProperty(),以防图表嵌入其他容器中。

I've wrapped the call to setMaxBarWidth() with Platform.runLater(), so the scene graph has time to refresh properly the chart, avoiding several repaints during the while loops. Also, I've moved the listener to bc.widthProperty(), in case the chart is embedded in other containers.