有没有办法设置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);
}
}
例如,有一种方法可以设置BarGap大小,但我找不到设置条形图列的最大宽度的方法。
有没有办法解决这个问题?
BarChart
基于用户可以设置barGap
(同一类别中条形之间的间隙(和categoryGap
(不同类别中条形之间的间隙(来工作,因此对于给定大小的图表,每次请求布局时都会在内部计算条形的宽度。
要设置每个柱的最大宽度,我们必须相应地更改barGap
或categoryGap
。但是我们可以以编程方式执行此操作,以响应图表宽度的任何变化。
让我们首先计算初始布局的条形宽度。根据BarChart.layoutPlotChildren()
:
double catSpace = xAxis.getCategorySpacing();
double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getBarGap());
double barWidth = (avilableBarSpace / bc.getData().size()) - bc.getBarGap();
在OP提供的示例中,给定默认间隙值(barGap=4
,categoryGap=10
(,结果barWidth
为37.4。
假设我们要设置限制 40,最小类别差距为 10:
double maxBarWidth=40;
double minCategoryGap=10;
如果调整场景大小时图表的宽度增加,我们可以通过增加categoryGap
来限制barWidth
:
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-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);
将所有内容放在一起,并聆听场景宽度的变化:
...
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);
}
});
请注意,在其余情况下,barWidth
将在内部计算。
进一步何塞·佩雷达的回答。您可以根据数据集设置图表的宽度。与BarGap和CategoryGap设置器一起,您可以通过计算或反复试验来微调条形的宽度。例如,我做了以下操作来获得更细的条形。我将空图表的宽度设置为 30(对于轴和标签??(,然后在 cribbage 游戏中每轮的最大宽度和最小宽度添加 100px(最多为网格窗格宽度的最大宽度(,从而限制了图表中供条填充的可用空间。
Pane barchart1 = new Pane;
CategoryAxis xAxis = new CategoryAxis();
NumberAxis yAxis = new NumberAxis(0,25,1);
BarChart<String, Number> bc1 =
new BarChart<String, Number>(xAxis, yAxis);
// create Player chart
bc1.setTitle(G.getPlayerName(0));
bc1.setTitle(null);
xAxis1.setLabel("Round");
yAxis1.setLabel("Points");
XYChart.Series series1 = new XYChart.Series();
series1.setName("Pegging");
XYChart.Series series3 = new XYChart.Series();
series3.setName("Hand");
XYChart.Series series5 = new XYChart.Series();
series5.setName("Box");
for (int i = 0; i < G.getRoundsSize(); i++) {
series1.getData().add(new XYChart.Data(Integer.toString(i + 1), G.getRound(i).getPlayerRoundData(0).getPegPoints()));
series3.getData().add(new XYChart.Data(Integer.toString(i + 1), G.getRound(i).getPlayerRoundData(0).getHandPoints()));
series5.getData().add(new XYChart.Data(Integer.toString(i + 1), G.getRound(i).getPlayerRoundData(0).getBoxPoints()));
}
bc1.getData(). addAll(series1, series3, series5);
bc1.setBarGap(0);
bc1.setCategoryGap(1.0);
bc1.setMaxHeight(180);
bc1.setMinHeight(180);
if(G.getRoundsSize() < 8){
int wid = ((G.getRoundsSize() * 100) + 30);
bc1.setMaxWidth(wid);
bc1.setMinWidth(wid);
} else {
bc1.setMaxWidth(830);
bc1.setMinWidth(830);
}
barchart1.getChildren().add(bc1);
你不能简单地在Javafx条形图中设置条形宽度。您只能设置类别CategoryGap
与类别BarGap
条形之间的距离。
由于类别的数量(categoryAxis.getCategories().size()
(,每个类别的条形(barChart.getData().size()
(和轴的可用空间(categoryAxis.getLayoutBounds().getWidth()
(是已知的,因此可以简单地计算CategoryGap
和BarGap
。
重要提示:如果调整了图表的大小,则需要重新计算。
public static void setBarWidth(BarChart<?, ?> barChart, CategoryAxis categoryAxis,
double barWidth, double availableSpace) {
int dataSeriesCount = barChart.getData().size();
int categoriesCount = categoryAxis.getCategories().size();
if (dataSeriesCount <= 1) {
barChart.setBarGap(0d);
} else {
barChart.setBarGap(5d);
}
double barWidthSum = barWidth * (categoriesCount * dataSeriesCount);
double barGapSum = barChart.getBarGap() * (dataSeriesCount - 1);
double categorySpacing = (availableSpace - barWidthSum - barGapSum) / categoriesCount;
barChart.setCategoryGap(categorySpacing);
}