Постер нашел решение этой проблемы с помощью класса ScatterExample
, реализующего интерфейс AxisChangeListener
.Пример обновлен до версии 1.5 .Также добавлена таблица для отображения истории изменений границ оси.На рисунке показан результат масштабирования, панорамирования и нажатия кнопок команд масштабирования, Увеличение до Сброс Y .
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Rectangle;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.event.AxisChangeEvent;
import org.jfree.chart.event.AxisChangeListener;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.chart.ChartFactory;
import static org.jfree.chart.ChartPanel.*;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.Axis;
import org.jfree.chart.axis.ValueAxis;
public final class ScatterExample implements AxisChangeListener {
private static final int N = 32; // data points per series
private static final int R = 10; // initial axis bounds
private final Random RANDOM = new Random();
private ChartPanel chartPanel = new ChartPanel(null, false) {
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
};
private final DefaultTableModel model = new DefaultTableModel(
new String[]{"Axis", "lower bound", "upper bound"}, 0) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
private final JTable table = new JTable(model) {
@Override
public Class<?> getColumnClass(int column) {
switch (column) {
case 0:
return String.class;
case 1:
return Double.class;
case 2:
return Double.class;
default:
return String.class;
}
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(250, 400);
}
};
public static void main(String[] args) {
EventQueue.invokeLater(new ScatterExample()::display);
}
private void display() {
XYSeriesCollection dataset = createSampleXYDataset();
JFreeChart chart = ChartFactory.createScatterPlot(
"Scatterplot", // chart title
"X", // domain axis label
"Y", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
true, // include legend?
true, // tooltips?
false // URLs?
);
XYPlot plot = chart.getXYPlot();
plot.setDomainPannable(true);
plot.getDomainAxis().setRange(-R, R);
plot.getDomainAxis().addChangeListener(this);
plot.setRangePannable(true);
plot.getRangeAxis().setRange(-R, R);
plot.getRangeAxis().addChangeListener(this);
chartPanel.setChart(chart);
table.setDefaultRenderer(Double.class, new DefaultTableCellRenderer() {
{
setHorizontalAlignment(JLabel.RIGHT);
}
NumberFormat f = new DecimalFormat("#.00");
@Override
protected void setValue(Object value) {
setText((value == null) ? "" : f.format(value));
}
});
JFrame f = new JFrame("Axis Range Example");
f.add(chartPanel);
f.add(createControls(), BorderLayout.SOUTH);
f.add(new JScrollPane(table), BorderLayout.EAST);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private XYSeriesCollection createSampleXYDataset() {
XYSeriesCollection d = new XYSeriesCollection();
XYSeries series1 = new XYSeries("Series 1");
XYSeries series2 = new XYSeries("Series 2");
for (int i = 0; i < N; i++) {
series1.add(RANDOM.nextGaussian(), RANDOM.nextGaussian());
series2.add(RANDOM.nextGaussian(), RANDOM.nextGaussian());
}
d.addSeries(series1);
d.addSeries(series2);
return d;
}
@Override
public void axisChanged(AxisChangeEvent event) {
Axis changed = event.getAxis();
ValueAxis domainAxis = chartPanel.getChart().getXYPlot().getDomainAxis();
ValueAxis rangeAxis = chartPanel.getChart().getXYPlot().getRangeAxis();
if (changed.equals(domainAxis)) {
double lower = domainAxis.getLowerBound();
double upper = domainAxis.getUpperBound();
model.addRow(new Object[]{"Domain", lower, upper});
}
if (changed.equals(rangeAxis)) {
double lower = rangeAxis.getLowerBound();
double upper = rangeAxis.getUpperBound();
model.addRow(new Object[]{"Range", lower, upper});
}
int last = table.getModel().getRowCount() - 1;
Rectangle r = table.getCellRect(last, 0, true);
table.scrollRectToVisible(r);
}
// @see https://stackoverflow.com/a/41544007/230513
private JPanel createControls() {
JPanel panel = new JPanel();
JToolBar toolBar = new JToolBar();
toolBar.add(createButton("Zoom In", ZOOM_IN_BOTH_COMMAND));
toolBar.add(createButton("Zoom In X", ZOOM_IN_DOMAIN_COMMAND));
toolBar.add(createButton("Zoom In Y", ZOOM_IN_RANGE_COMMAND));
toolBar.add(createButton("Zoom Out", ZOOM_OUT_BOTH_COMMAND));
toolBar.add(createButton("Zoom Out X", ZOOM_OUT_DOMAIN_COMMAND));
toolBar.add(createButton("Zoom Out Y", ZOOM_OUT_RANGE_COMMAND));
toolBar.add(createButton("Reset", ZOOM_RESET_BOTH_COMMAND));
toolBar.add(createButton("Reset X", ZOOM_RESET_DOMAIN_COMMAND));
toolBar.add(createButton("Reset Y", ZOOM_RESET_RANGE_COMMAND));
panel.add(toolBar);
return panel;
}
private JButton createButton(String name, String command) {
final JButton b = new JButton(name);
b.setActionCommand(command);
b.addActionListener(chartPanel);
return b;
}
}