目次 ⇒ JFreeChartサンプル
package jp.avaj.lib.chart;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Paint;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import jp.avaj.lib.algo.ArUtil;
import jp.avaj.lib.test.L;
/**
■ JFreeChart-XYPlot-クリック時に値を取得し十字線を表示する.
・概要と注意事項.
・ChartPanelにMouseListenerを設定する.
・クリックした時に十字線を表示する.
・この時の対象位置は、クリック点の位置ではなく、対角線で一番近い点である.
・グラフからちょっと離れた部分をクリックしてみるとよい.
・MouseListener中でデータを取得すると前回クリックのデータが取得される.
・対策として本サンプルでは別スレッド中で取得する方法を提示している.
・取得されたデータはdoubleなので、意味のある値(例えば日付など)に変換が必要な場合がある.
・値は取得できるが、グラフは取得できないので、取得された値から検索する必要がある.
*/
public class Chart19_02 {
public static void main(String[] args) throws IOException {
//
XYDataset dataset = createDataset();
//
NumberAxis yAxis = new NumberAxis();
yAxis.setAutoRangeIncludesZero(true);
NumberAxis xAxis = new NumberAxis();
XYLineAndShapeRenderer xyLineAndShapeRenderer = new XYLineAndShapeRenderer();
XYPlot xyPlot = new XYPlot(dataset,(ValueAxis)xAxis,(ValueAxis)yAxis,(XYItemRenderer)xyLineAndShapeRenderer);
// 十字線の属性の登録
{
BasicStroke stroke = new BasicStroke(3.0F);
xyPlot.setDomainCrosshairStroke((Stroke)stroke);
xyPlot.setRangeCrosshairStroke((Stroke)stroke);
Color color = Color.red;
xyPlot.setDomainCrosshairPaint((Paint)color);
xyPlot.setRangeCrosshairPaint((Paint)color);
}
JFreeChart jfreeChart = new JFreeChart("売上データ",(Plot)xyPlot);
//
ChartFrame cFrame = new ChartFrame("売上データ",(JFreeChart)jfreeChart);
cFrame.pack();
cFrame.setVisible(true);
// リスナーの登録
ChartPanel chartPanel = cFrame.getChartPanel();
chartPanel.addMouseListener(new MyMouseListener());
// データ取得用のスレッド
(new MyThread(xyPlot)).start();
}
/**
* データ取得用のスレッド
* 今回は単にループし取得データを表示するだけにしている.
* アプリケーションの他の部分との受け渡しは、個別に考える必要がある.
*/
private static class MyThread extends Thread {
public MyThread(XYPlot xyPlot) {
this.xyPlot = xyPlot;
}
public void run() {
for (;;) {
// 少し休む
ArUtil.sleep(2000);
double x = xyPlot.getDomainCrosshairValue();
L.p("X(Thread)="+x);
double y = xyPlot.getRangeCrosshairValue();
L.p("Y(thread)="+y);
}
}
private XYPlot xyPlot;
}
/** マウスリスナークラス */
private static class MyMouseListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent ev) {
ChartPanel chartPanel = (ChartPanel)ev.getSource();
JFreeChart jfreeChart = chartPanel.getChart();
XYPlot xyPlot = jfreeChart.getXYPlot();
// 十字線を表示する
xyPlot.setRangeCrosshairVisible(true);
xyPlot.setDomainCrosshairVisible(true);
// リスナーの中で取得すると前回の値が取得されることを示す
double x = xyPlot.getDomainCrosshairValue();
L.p("X="+x);
double y = xyPlot.getRangeCrosshairValue();
L.p("Y="+y);
}
}
/** テストデータを作成する */
private static XYDataset createDataset() {
XYSeriesCollection dataset = new XYSeriesCollection();
// 一本目
XYSeries xySeries = new XYSeries("data-0");
for (int j=0; j<10; j++) {
xySeries.add(j,j+Math.random()*4.0D);
}
dataset.addSeries(xySeries);
// 二本目
xySeries = new XYSeries("data-1");
for (int j=0; j<10; j++) {
xySeries.add(j,9-j+Math.random()*4.0D);
}
dataset.addSeries(xySeries);
return dataset;
}
}
/* 結果------------------------------------------------
X(Thread)=0.0
Y(thread)=0.0
X=0.0
Y=0.0
X(Thread)=6.0
Y(thread)=4.135505502289391
X(Thread)=6.0
Y(thread)=4.135505502289391
X(Thread)=6.0
Y(thread)=4.135505502289391
X=6.0
Y=4.135505502289391
X(Thread)=2.0
Y(thread)=9.601015398325675
X(Thread)=2.0
Y(thread)=9.601015398325675
----------------------------------------------------- */