我正在编写一个javafx
程序,该程序应该显示BubbleChart
来分析公司。在y轴上显示去年收入,在x轴上显示公司经营的细分市场数量。泡沫的半径取决于公司经营的细分市场。
我知道我可以写一个“泡沫”:
new XYChart.Data<Number,Number>(nbrOfMarketSegments, latestYearRevenue, radiusOfBubble);
问题是y轴最大值为100(百万欧元),x轴最大值为20,这使得“气泡”非常平坦,如图所示(因为radiusOfBubble
数字比较大最大市场细分数量与最大收入相比较小。我的问题是,即使x轴和y轴具有不同的跨度,有没有办法让气泡更像圆圈?
答案 0 :(得分:5)
JavaFX图表是一段邪恶的代码。只有在您完全了解背后的代码库时才能实现自适应,这在某种程度上违背了信息隐藏的良好原则。在BubbleChart
中获取圆形气泡是其中一种适应方式。
您可以做的最简单的事情是继承BubbleChart
并创建自己的圆形气泡。
不起作用的事情:
创建数据节点的位置(方法createBubble
)是私有的,因此您无法覆盖它以创建Circle
。 (除此之外 - 即使你有一个自定义数据节点,它也无法正常工作,因为BubbleChart
中的布局代码会忽略所有不属于Ellipse
类型的数据节点,所以你最终会有圆形气泡,但都在位置(0/0)......)。
接下来要考虑的是覆盖省略号轴的设置位置。但不是,所有的布局代码都是一个单一的方法 - 没有layoutNode(Node)
- 为每个节点调用的方法,你可以覆盖它来添加自定义布局代码。
<强>解决方案:强>
所以你必须覆盖方法layoutPlotChildren
,调用基础实现,然后改变所有节点的Y半径:
public class CircularBubbleChart<X, Y> extends BubbleChart<X, Y> {
public CircularBubbleChart(Axis<X> xAxis, Axis<Y> yAxis) {
super(xAxis, yAxis);
}
public CircularBubbleChart(Axis<X> xAxis, Axis<Y> yAxis, ObservableList<Series<X, Y>> data) {
super(xAxis, yAxis, data);
}
@Override
protected void layoutPlotChildren() {
super.layoutPlotChildren();
getData().stream().flatMap(series -> series.getData().stream())
.map(Data::getNode)
.map(StackPane.class::cast)
.map(StackPane::getShape)
.map(Ellipse.class::cast)
.forEach(ellipse -> ellipse.setRadiusY(ellipse.getRadiusX()));
}
}
用法很简单:只需将图表创建代码行从... = new BubbleChart()
更改为... = new CircularBubbleChart()
即可。其他一切都保持不变。
注意:此代码将Y-Radius更改为等于X-Radius,因此气泡半径将以X轴为单位。当然,你也可以反过来获得以Y轴为单位的气泡半径。