Как изменить размер пузырьков в BubbleChart javafx

Я пишу программу javafx, которая должна показывать BubbleChart для анализа компаний. По оси y отображаются доходы за прошлый год, а по оси x отображается количество сегментов рынка, в которых работает компания. Радиус пузыря зависит от того, в каких сегментах рынка работает компания.

Я знаю, что могу сделать «пузырь», написав:

new XYChart.Data<Number,Number>(nbrOfMarketSegments, latestYearRevenue, radiusOfBubble);

Проблема в том, что максимум по оси Y равен 100 (миллионам евро), а максимум по оси X равен 20, что делает «пузыри» очень плоскими, как на картинке (поскольку число radiusOfBubble велико по сравнению с максимальным количеством сегментов рынка и маленькими по сравнению с максимальным доходом Мой вопрос: есть ли способ сделать пузыри более круглыми, даже если ось X и ось Y имеют такие разные промежутки?

Пузырьковая диаграмма


person ekstroom    schedule 27.07.2016    source источник


Ответы (1)


Диаграммы 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 равным радиусу X, поэтому радиус пузырька будет измеряться в единицах оси X. Конечно, вы можете и наоборот получить радиус пузырька в единицах оси Y.

person isnot2bad    schedule 27.07.2016
comment
Спасибо! Это очень полезно! - person ekstroom; 29.07.2016