В дополнение к принятому ответу я бы хотел опубликовать ответ сам, потому что столкнулся с парой вопросов, касающихся SlidingXYDataset
:
Реализация позволяет указатьколичество точек в наборе данных, которое может быть показано в любой момент времени, и это нормально для большинства случаев использования.Но в случае, когда точки данных разбросаны очень равномерно в скользящем наборе данных, данные заставят ось домена изменить свой диапазон.Например, если размер окна равен 5 точкам данных, а первые 5 - это 2 единицы, а следующие 5 - 20 единиц, то размер видимого диапазона оси X изменится при скольжении.Таким образом, вы можете увидеть, как будет выглядеть поведение, когда все точки нанесены на график в произвольных местах.Это может или не может быть желательным поведением.В моем случае мне нужно было иметь фиксированный видимый диапазон оси X (например, 200 единиц) и постоянно сохранять его таким.
По какой-то причине я не смогсоздать SlidingXYDataset
, задав ему пустое XYSeriesCollection/TimeSeriesCollection
.Мне нужно было начать с пустого набора данных и обновлять его в режиме реального времени, и мне пришлось добавлять бесполезные данные для начала.Но это может быть потому, что я делал что-то не так.
Сказав это выше, могут быть обходные пути для этого, но я пошел и реализовал масштабирование и полосу прокрутки иначе, чем принятый ответ.
Также в этом примере показано, как синхронизировать ползунок, когда пользователь выполняет действие масштабирования на графике.
Во-первых: вам нужно создать XYLineChart
и установить желаемый диапазон ( Пример разработан только для оси X, но может применяться и для оси Y )
XYSeries dataset = new XYSeries("my dataset");
XYSeriesCollection datasetCollection = new XYSeriesCollection(dataset);
JFreeChart chart = ChartFactory.createXYLineChart("title",
"x label",
"y label",
datasetCollection,
PlotOrientation.VERTICAL,
true, false, false);
XYPlot plot = chart.getXYPlot();
ValueAxis domainAxis = plot.getDomainAxis();
ValueAxis rangeAxis = plot.getRangeAxis();
domainAxis.setAutoRange(false);
domainAxis.setFixedAutoRange(300); // 300 units visible at anytime on X axis
domainAxis.setLowerBound(0); // start from 0
Второе: вам нужно поместить диаграмму и полосу прокрутки внутри родительского макета.В SWT вы можете сделать это, например, через пользователя FormLayout
// Given that composite is the parent Composite
FormLayout layout = new FormLayout();
composite.setLayout(layout);
chartComposite = new ChartComposite(composite, SWT.NONE, chart, true);
Slider slider = new Slider(composite, SWT.NONE);
sldier.setValues(/* depends on your needs */);
// add the slider to the bottom of the form
FormData sliderLayoutData = new FormData();
sliderLayoutData.left = new FormAttachment(0,0);
sliderLayoutData.bottom = new FormAttachment(100,0);
sliderLayoutData.right = new FormAttachment(100,0);
slider.setLayoutData(sliderLayoutData);
// now add the graphComposite to the form above the slider
FormData graphLayoutData = new FormData();
graphLayoutData.left = new FormAttachment(0,0);
graphLayoutData.right = new FormAttachment(100,0);
graphLayoutData.top = new FormAttachment(0,0);
graphLayoutData.bottom = new FormAttachment(slider);
chartComposite.setLayoutData(graphLayoutData);
// refresh the layout
composite.layout(true);
Теперь каждый раз, когда вы перемещаете ползунок, вам нужно захватить это событие и изменить диапазон доменов диаграммы с помощьюк методам по данным вашего слайдера:
domainAxis.setLowerBound(minimum visible);
domainAxis.setUpperBound(maximum visible);
Третье: наконец, вам нужно переопределить метод масштабирования ChartComposite, либо расширив этот объект, либо прямо над ним при создании нового
@Override
public void zoom(Rectangle selection)
{
XYPlot plot = (XYPlot) getChart().getPlot();
Rectangle2D plotArea = new Rectangle2D.Double( getScreenDataArea().x,
getScreenDataArea().y,
getScreenDataArea().width,
getScreenDataArea().height);
float x1 = (float) plot.getDomainAxis().
java2DToValue(selection.x,
plotArea,
plot.getDomainAxisEdge());
float x2 = (float) plot.getDomainAxis().
java2DToValue(selection.x + selection.width,
plotArea,
plot.getDomainAxisEdge());
// x1 and x2 will have the points transalted into chart coordinates
// of the selection the user made for zooming the X axis
// you can adjust your chart to show only the selected (zoomed)
// information as such
domainAxis.setLowerBound(x1);
domainAxis.setUpperBound(x2);
// and now adjust the slider information so it's
// synced to your graph's current view
sldier.setValues(/* depends on your needs */);
}
Надеюсь, что эта реализация найдет применение вслучаи использования других людей.