I created simple example of Bar Chart but I notices that size of the bar fits the chart. How I can limit the size? Foe example I would like to limit the width size.
Asked
Active
Viewed 4,150 times
1 Answers
5
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.
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);
}
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));
});
}
EDIT
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.

Community
- 1
- 1

José Pereda
- 44,311
- 7
- 104
- 132
-
Your example is good but there is one small problem that I need to describe. I have a SplitPane in which I have VBox which holds the chart. In every test I have the old result. But when I drag the SplitPane I get the desired result. Look like the Width is not properly calculated. Any idea how I can do this on the first load? – Peter Penzov Jan 21 '15 at 13:38
-
You need to listen to changes in the `VBox` width, so everytime its resized, the bar chart width is also recalculated. – José Pereda Jan 21 '15 at 13:41
-
I tested to remove entirely VBox and directly to insert the chart into SplitPane but still there is no solution. – Peter Penzov Jan 21 '15 at 13:59
-
Check my edit, now it should work within a `VBox` inside a `SplitPane`. – José Pereda Jan 21 '15 at 14:16
-
According to javadoc: *runLater runs the specified Runnable on the JavaFX Application Thread at some unspecified time in the future*. This avoids multiples repaints of the chart. – José Pereda Jan 21 '15 at 14:28
-
Any other alternative solution? – Peter Penzov Jan 21 '15 at 14:29
-
I don't see the problem there. But maybe you could run a background task instead. – José Pereda Jan 21 '15 at 14:30
-
Well, for now the problem is solved. Any idea is this going to be fixed in future JavaFX versions? – Peter Penzov Jan 21 '15 at 14:52
-
There are bug reports on JIRA, marked as unresolved, like [this](https://javafx-jira.kenai.com/browse/RT-21294), scheduled for Java 9... – José Pereda Jan 21 '15 at 14:57
-
One more question again: with Platform.runLater I can solve temporary the problem. Is there another solution like taking Pref size of the parent component? – Peter Penzov Jan 21 '15 at 15:17
-
I don't think so. You could try some bindings, but there are many variables involved, and iterative calculations. I think the solution, if any, would be worst. `Platform.runLater()` is really useful here and I wouldn't worry about adding a thread only for the case when the chart is resized. – José Pereda Jan 21 '15 at 15:26
-
This is not working for me. Barchart is not being displayed.After calling the setMaxBarWidth() method, barchart.setCategoryGap is being set to NaN. – mistletoe Feb 17 '17 at 15:12