One approach is to render arbitrary content in a Canvas
, as suggested here. The corresponding GraphicsContext
gives you maximum control of the coordinates. As a concrete example, jfreechart renders charts using jfreechart-fx
, whose ChartViewer
holds a ChartCanvas
that extends Canvas
. Starting from this example, the variation below sets the domain axis to span an interval centered on zero after adding corresponding points to the three series. Use the mouse wheel or context menu to zoom; see this related answer for more on zooming and panning.
for (double t = -3; t <= 3; t += 0.5) {
series.add(t, Math.sin(t) + i);
}
…
xAxis.setRange(-Math.PI, Math.PI);
…
plot.setDomainPannable(true);

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.entity.LegendItemEntity;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.fx.ChartViewer;
import org.jfree.chart.fx.interaction.ChartMouseEventFX;
import org.jfree.chart.fx.interaction.ChartMouseListenerFX;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* @see https://stackoverflow.com/a/44967809/230513
* @see https://stackoverflow.com/a/43286042/230513
*/
public class VisibleTest extends Application {
@Override
public void start(Stage stage) {
XYSeriesCollection dataset = new XYSeriesCollection();
for (int i = 0; i < 3; i++) {
XYSeries series = new XYSeries("value" + i);
for (double t = -3; t <= 3; t += 0.5) {
series.add(t, Math.sin(t) + i);
}
dataset.addSeries(series);
}
NumberAxis xAxis = new NumberAxis("domain");
xAxis.setRange(-Math.PI, Math.PI);
NumberAxis yAxis = new NumberAxis("range");
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true, true);
renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());
XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer);
JFreeChart chart = new JFreeChart("Test", plot);
ChartViewer viewer = new ChartViewer(chart);
viewer.addChartMouseListener(new ChartMouseListenerFX() {
@Override
public void chartMouseClicked(ChartMouseEventFX e) {
ChartEntity ce = e.getEntity();
if (ce instanceof XYItemEntity) {
XYItemEntity item = (XYItemEntity) ce;
renderer.setSeriesVisible(item.getSeriesIndex(), false);
} else if (ce instanceof LegendItemEntity) {
LegendItemEntity item = (LegendItemEntity) ce;
Comparable key = item.getSeriesKey();
renderer.setSeriesVisible(dataset.getSeriesIndex(key), false);
} else {
for (int i = 0; i < dataset.getSeriesCount(); i++) {
renderer.setSeriesVisible(i, true);
}
}
}
@Override
public void chartMouseMoved(ChartMouseEventFX e) {}
});
stage.setScene(new Scene(viewer));
stage.setTitle("JFreeChartFX");
stage.setWidth(640);
stage.setHeight(480);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}