堆叠条形图的限制宽度大小
Limit width size of Stacked Bar chart
我尝试为 StackedBar Chart 实施 解决方案,但事实证明 StackedBar 图表中没有 Java 方法 getBarGap()
。最新的 JavaFX 版本是否有针对此问题的任何解决方案?
基本示例:
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class MainApp extends Application
{
private StackedBarChart<String, Number> stackedChart;
private List<EventsObj> eventsObj;
@Override
public void start(Stage stage) throws Exception
{
createStackedChart();
List<EventsObj> testData = generateTestData();
addStackedChartData(testData);
HBox hb = new HBox();
hb.getChildren().add(stackedChart);
Scene scene = new Scene(hb);
stage.setTitle("JavaFX and Maven");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args)
{
launch(args);
}
private void createStackedChart()
{
CategoryAxis xAxis = new CategoryAxis();
xAxis.setLabel("Days");
NumberAxis yAxis = new NumberAxis();
stackedChart = new StackedBarChart<>(xAxis, yAxis);
stackedChart.setCategoryGap(20);
stackedChart.widthProperty().addListener((obs, b, b1) ->
{
// Chart Bar column is not automatically resized. We need to wait for next JavaFX releases to fix this.
Platform.runLater(() -> setMaxBarWidth(stackedChart, xAxis, 40, 10));
});
}
private List<EventsObj> generateTestData()
{
eventsObj = new ArrayList<>();
for (int i = 0; i < 5; i++)
{
eventsObj.add(new EventsObj(String.valueOf(randomDate()), random(2, 60), random(2, 60), random(2, 60), random(2, 60)));
}
return eventsObj;
}
public static int random(int lowerBound, int upperBound)
{
return (lowerBound + (int) Math.round(Math.random() * (upperBound - lowerBound)));
}
private LocalDate randomDate()
{
Random random = new Random();
int minDay = (int) LocalDate.of(1900, 1, 1).toEpochDay();
int maxDay = (int) LocalDate.of(2015, 1, 1).toEpochDay();
long randomDay = minDay + random.nextInt(maxDay - minDay);
LocalDate randomBirthDate = LocalDate.ofEpochDay(randomDay);
return randomBirthDate;
}
private void addStackedChartData(List<EventsObj> data)
{
List<XYChart.Series<String, Number>> dataSeries = new ArrayList<>(data.size());
for (EventsObj data1 : data)
{
final XYChart.Series<String, Number> series1 = new XYChart.Series<>();
series1.setName(data1.getDate());
series1.getData().setAll(
new XYChart.Data<>("Info", data1.getInfo()));
dataSeries.add(series1);
}
stackedChart.getData().setAll(dataSeries);
}
private void setMaxBarWidth(StackedBarChart<String, Number> bc, CategoryAxis xAxis, double maxBarWidth, double minCategoryGap)
{
double barWidth = 0;
do
{
double catSpace = xAxis.getCategorySpacing();
double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getCategoryGap());
barWidth = (avilableBarSpace / bc.getData().size()) - bc.getCategoryGap();
if (barWidth > maxBarWidth)
{
avilableBarSpace = (maxBarWidth + bc.getCategoryGap()) * bc.getData().size();
bc.setCategoryGap(catSpace - avilableBarSpace - bc.getCategoryGap());
}
}
while (barWidth > maxBarWidth);
do
{
double catSpace = xAxis.getCategorySpacing();
double avilableBarSpace = catSpace - (minCategoryGap + bc.getCategoryGap());
barWidth = Math.min(maxBarWidth, (avilableBarSpace / bc.getData().size()) - bc.getCategoryGap());
avilableBarSpace = (barWidth + bc.getCategoryGap()) * bc.getData().size();
bc.setCategoryGap(catSpace - avilableBarSpace - bc.getCategoryGap());
}
while (barWidth < maxBarWidth && bc.getCategoryGap() > minCategoryGap);
}
}
在 BarChart
图表中,添加的不同系列绘制在同一类别的不同列中,具有 barGap,中间有一些间距。
但在 StackBarChart
图表中,不同的系列堆叠在同一列中,因此在这种情况下没有条形间隙。
如果从这个取setMaxBarWidth()
方法,只需要将bc.getBarGap()
设为0,sbc.getData().size()
设为1即可。在不需要迭代的情况下。
这将是真正简化的新方法:
private void setMaxCategoryWidth(double maxCategoryWidth, double minCategoryGap){
double catSpace = xAxis.getCategorySpacing();
sbc.setCategoryGap(catSpace - Math.min(maxCategoryWidth, catSpace - minCategoryGap));
}
基本上,您所要做的就是从类别的初始宽度中减去类别的所需宽度,然后将这个额外的 space 放入 categoryGap。
现在,您可以创建图表:
StackedBarChart<String, Number> sbc = new StackedBarChart<>(xAxis, yAxis);
并设置您想要的类别大小:
setMaxCategoryWidth(40, 10);
sbc.widthProperty().addListener((obs, b, b1) -> {
Platform.runLater(() -> setMaxCategoryWidth(40, 10));
});
此图片是根据取自 here 的样本 7.4 生成的。
我尝试为 StackedBar Chart 实施 getBarGap()
。最新的 JavaFX 版本是否有针对此问题的任何解决方案?
基本示例:
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class MainApp extends Application
{
private StackedBarChart<String, Number> stackedChart;
private List<EventsObj> eventsObj;
@Override
public void start(Stage stage) throws Exception
{
createStackedChart();
List<EventsObj> testData = generateTestData();
addStackedChartData(testData);
HBox hb = new HBox();
hb.getChildren().add(stackedChart);
Scene scene = new Scene(hb);
stage.setTitle("JavaFX and Maven");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args)
{
launch(args);
}
private void createStackedChart()
{
CategoryAxis xAxis = new CategoryAxis();
xAxis.setLabel("Days");
NumberAxis yAxis = new NumberAxis();
stackedChart = new StackedBarChart<>(xAxis, yAxis);
stackedChart.setCategoryGap(20);
stackedChart.widthProperty().addListener((obs, b, b1) ->
{
// Chart Bar column is not automatically resized. We need to wait for next JavaFX releases to fix this.
Platform.runLater(() -> setMaxBarWidth(stackedChart, xAxis, 40, 10));
});
}
private List<EventsObj> generateTestData()
{
eventsObj = new ArrayList<>();
for (int i = 0; i < 5; i++)
{
eventsObj.add(new EventsObj(String.valueOf(randomDate()), random(2, 60), random(2, 60), random(2, 60), random(2, 60)));
}
return eventsObj;
}
public static int random(int lowerBound, int upperBound)
{
return (lowerBound + (int) Math.round(Math.random() * (upperBound - lowerBound)));
}
private LocalDate randomDate()
{
Random random = new Random();
int minDay = (int) LocalDate.of(1900, 1, 1).toEpochDay();
int maxDay = (int) LocalDate.of(2015, 1, 1).toEpochDay();
long randomDay = minDay + random.nextInt(maxDay - minDay);
LocalDate randomBirthDate = LocalDate.ofEpochDay(randomDay);
return randomBirthDate;
}
private void addStackedChartData(List<EventsObj> data)
{
List<XYChart.Series<String, Number>> dataSeries = new ArrayList<>(data.size());
for (EventsObj data1 : data)
{
final XYChart.Series<String, Number> series1 = new XYChart.Series<>();
series1.setName(data1.getDate());
series1.getData().setAll(
new XYChart.Data<>("Info", data1.getInfo()));
dataSeries.add(series1);
}
stackedChart.getData().setAll(dataSeries);
}
private void setMaxBarWidth(StackedBarChart<String, Number> bc, CategoryAxis xAxis, double maxBarWidth, double minCategoryGap)
{
double barWidth = 0;
do
{
double catSpace = xAxis.getCategorySpacing();
double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getCategoryGap());
barWidth = (avilableBarSpace / bc.getData().size()) - bc.getCategoryGap();
if (barWidth > maxBarWidth)
{
avilableBarSpace = (maxBarWidth + bc.getCategoryGap()) * bc.getData().size();
bc.setCategoryGap(catSpace - avilableBarSpace - bc.getCategoryGap());
}
}
while (barWidth > maxBarWidth);
do
{
double catSpace = xAxis.getCategorySpacing();
double avilableBarSpace = catSpace - (minCategoryGap + bc.getCategoryGap());
barWidth = Math.min(maxBarWidth, (avilableBarSpace / bc.getData().size()) - bc.getCategoryGap());
avilableBarSpace = (barWidth + bc.getCategoryGap()) * bc.getData().size();
bc.setCategoryGap(catSpace - avilableBarSpace - bc.getCategoryGap());
}
while (barWidth < maxBarWidth && bc.getCategoryGap() > minCategoryGap);
}
}
在 BarChart
图表中,添加的不同系列绘制在同一类别的不同列中,具有 barGap,中间有一些间距。
但在 StackBarChart
图表中,不同的系列堆叠在同一列中,因此在这种情况下没有条形间隙。
如果从这个setMaxBarWidth()
方法,只需要将bc.getBarGap()
设为0,sbc.getData().size()
设为1即可。在不需要迭代的情况下。
这将是真正简化的新方法:
private void setMaxCategoryWidth(double maxCategoryWidth, double minCategoryGap){
double catSpace = xAxis.getCategorySpacing();
sbc.setCategoryGap(catSpace - Math.min(maxCategoryWidth, catSpace - minCategoryGap));
}
基本上,您所要做的就是从类别的初始宽度中减去类别的所需宽度,然后将这个额外的 space 放入 categoryGap。
现在,您可以创建图表:
StackedBarChart<String, Number> sbc = new StackedBarChart<>(xAxis, yAxis);
并设置您想要的类别大小:
setMaxCategoryWidth(40, 10);
sbc.widthProperty().addListener((obs, b, b1) -> {
Platform.runLater(() -> setMaxCategoryWidth(40, 10));
});
此图片是根据取自 here 的样本 7.4 生成的。