Replies: 1 comment
-
@thhart thanks for your interest in our little lib. Well, in part this might be because having multiple axes is inherently a bit complex because one cannot assume that each DataSet/Renderer is associated with the same 'x-' or 'y-' Axis. Unfortunately, there is no magic code w/o losing generality/flexibility. If this is too much boiler-plate code, then you may choose to define some factory methods that are handy for your specific application case. In any case, the example code is less than 100 SLOCs and shows most of the functionality that is available. You may pick-and-choose what you need and drop the rest. Out of the ~100 SLOCs, a large part is related to JavaFX boilerplate (imports, main/start-routine, setting up scene) which we like to keep explicit and not hide behind an unnecessarily large abstract demo-application class (i.e. the code can be copy-pasted into other projects and should work as is w/o hidden extra class dependencies), the other part is setting up and customizing the axes, i.e. final DefaultNumericAxis xAxis1 = new DefaultNumericAxis("x axis");
xAxis1.setAnimated(false);
final DefaultNumericAxis xAxis2 = new DefaultNumericAxis("x axis2");
xAxis2.setSide(Side.TOP);
xAxis2.setAnimated(false);
final DefaultNumericAxis yAxis1 = new DefaultNumericAxis("y axis", "random");
yAxis1.setAnimated(false);
final DefaultNumericAxis yAxis2 = new DefaultNumericAxis("y axis", "sine/cosine");
// yAxis2.setSide(Side.LEFT); // unusual but possible case
yAxis2.setSide(Side.RIGHT);
yAxis2.setAnimated(false);
final DefaultNumericAxis yAxis3 = new DefaultNumericAxis("y axis", "gauss");
yAxis3.setSide(Side.RIGHT);
yAxis3.invertAxis(true);
yAxis3.setAnimated(false); setting up the chart and adding the axes above to the specific renderer: final XYChart chart = new XYChart(xAxis1, yAxis1);
// N.B. it's important to set secondary axis on the 2nd renderer before
// adding the renderer to the chart
final ErrorDataSetRenderer errorRenderer1 = new ErrorDataSetRenderer();
errorRenderer1.getAxes().add(yAxis1);
final ErrorDataSetRenderer errorRenderer2 = new ErrorDataSetRenderer();
errorRenderer2.getAxes().add(yAxis2);
final ErrorDataSetRenderer errorRenderer3 = new ErrorDataSetRenderer();
errorRenderer3.getAxes().addAll(xAxis2, yAxis3);
chart.getRenderers().addAll(errorRenderer2, errorRenderer3);
chart.getPlugins().add(new ParameterMeasurements());
chart.getPlugins().add(new DataPointTooltip());
final Zoomer zoom = new Zoomer();
// add axes that shall be excluded from the zoom action
zoom.omitAxisZoomList().add(yAxis3);
// alternatively (uncomment):
Zoomer.setOmitZoom(xAxis2, true);
chart.getPlugins().add(zoom);
chart.getToolBar().getChildren().add(new MyZoomCheckBox(zoom, yAxis3));
chart.getPlugins().add(new EditAxis()); N.B. axes are internally attached to both the axes (for keeping track of the ranges, ticks etc. needed to correctly draw the DataSets) and chart (for drawing the axes itself). The idea of this example is not to show a minimalistic version of having, for example, only 2 vertical axes -- which would immediately pose questions like how to modify/shift/customize them -- but to go a bit beyond that to show what is possible, the overall mechanics, and how to adapt different settings. The public static Runnable getTask(final Renderer renderer1, final Renderer renderer2, final Renderer renderer3) {
return new Runnable() {
private int updateCount;
@Override
public void run() {
Platform.runLater(() -> {
// setAll in order to implicitly clear previous list of
// 'old' data sets
renderer1.getDatasets().setAll(new RandomWalkFunction("random walk", MultipleAxesSample.N_SAMPLES));
renderer2.getDatasets().setAll(new CosineFunction("cosy", MultipleAxesSample.N_SAMPLES, true),
new SineFunction("siny", MultipleAxesSample.N_SAMPLES, true));
renderer3.getDatasets().setAll(new GaussFunction("gaussy", MultipleAxesSample.N_SAMPLES));
if (updateCount % 10 == 0) {
LOGGER.atInfo().log("update iteration #" + updateCount);
}
updateCount++;
});
}
};
} In the example this function is called explicitly only once as Hope this little meta-information helps with your project. Also, let us know if you have a more suitable API suggestion that is easier while not losing the flexibility/customizability for the more elaborated cases. We are about to prepare a new minor-version sprint where we plan to modernise/simplify some the -- albeit mostly internal -- library code. |
Beta Was this translation helpful? Give feedback.
-
Hi, maybe I am too lazy but the example for multiple axis support looks extremely complex and hard to understand for someone who is not into all concepts of your library. It combines rendering, datasets, threading, plugins and other stuff which makes it extremely hard to distinguish what is essential for multiple axis to handle. Maybe you can add another more simpler example.
Beta Was this translation helpful? Give feedback.
All reactions