jfreechart 对于鼠标事件响应的扩展

    jfreechart是一个优秀的开源chart软件。利用jfreechart可以绘制出各种丰富和优美的图形。但是在jfreechart的图上对于鼠标的支持不很充分,对于鼠标的clicked、moved、pressed、released、entered、exited的事件只支持了两个clicked和moved(不知道为什么?),幸运的是jfreechart是一个开源的软件,可以对于它的实现进行升级,在它传统的功能基础上,实现自己的功能需求。

   jfreechart中的鼠标事件实现机制为:一是扩展java.util.EventListener接口为ChartMouseListener,在其中定义了chartMouseClicked和chartMouseMoved两个事件响应函数;而是继承java.util.EventObject类生成ChartMouseEvent,在ChartMouseEvent中封装了鼠标事件和Jfreechart的对象,供事件处理函数中应用;三是在jfreechart的ChartPanel中定义了事件监听器队列,当外部程序注册了事件监听器后,在chartpanel中发生定义的事件后,监听器响应响应的事件。

   在jfreechart默认的实现中,对于鼠标事件,只有clicked和moved可以供外部监听,其他事件提供了默认的监听实现,这样就阻碍了外部对jfreechart的更深入的鼠标操作。

   为了实现其它事件能够被外部监听器监听,首先需要对ChartPanel中的事件监听机制进行调整,这里我利用MyChartPanel继承ChartPanel,重载其中所需要被外部监听器监听的事件的实现函数,把事件发给外部的监听器,类定义如下所示:

import java.awt.Insets;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;

import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.entity.EntityCollection;

@SuppressWarnings("serial")
public class MyChartPanel extends ChartPanel {


	public MyChartPanel(JFreeChart chart) {
		super(chart);
		// TODO Auto-generated constructor stub
	}

	/* (non-Javadoc)
	 * @see org.jfree.chart.ChartPanel#mousePressed(java.awt.event.MouseEvent)
	 */
	@Override
	public void mousePressed(MouseEvent event) {
		// TODO Auto-generated method stub
	       Insets insets = getInsets();
	        int x = (int) ((event.getX() - insets.left) /this.scaleX);
	        int y = (int) ((event.getY() - insets.top) / this.scaleY);

	        this.anchor = new Point2D.Double(x, y);
	        if (this.chart == null) {
	            return;
	        }
	        this.chart.setNotify(true);  // force a redraw
	        // new entity code...
	        Object[] listeners = this.chartMouseListeners.getListeners(
	                ChartMouseListener.class);
	        if (listeners.length == 0) {
	            return;
	        }

	        ChartEntity entity = null;
	        if (this.info != null) {
	            EntityCollection entities = this.info.getEntityCollection();
	            if (entities != null) {
	                entity = entities.getEntity(x, y);
	            }
	        }
	        ChartMouseEvent chartEvent = new ChartMouseEvent(getChart(), event,
	                entity);
	        for (int i = listeners.length - 1; i >= 0; i -= 1) {
	            ((MyChartMouseListener) listeners[i]).chartMousePressed(chartEvent);
	        }
	}

	/* (non-Javadoc)
	 * @see org.jfree.chart.ChartPanel#mouseReleased(java.awt.event.MouseEvent)
	 */
	@Override
	public void mouseReleased(MouseEvent event) {
		// TODO Auto-generated method stub
	       Insets insets = getInsets();
	        int x = (int) ((event.getX() - insets.left) /this.scaleX);
	        int y = (int) ((event.getY() - insets.top) / this.scaleY);

	        this.anchor = new Point2D.Double(x, y);
	        if (this.chart == null) {
	            return;
	        }
	        this.chart.setNotify(true);  // force a redraw
	        // new entity code...
	        Object[] listeners = this.chartMouseListeners.getListeners(
	                ChartMouseListener.class);
	        if (listeners.length == 0) {
	            return;
	        }

	        ChartEntity entity = null;
	        if (this.info != null) {
	            EntityCollection entities = this.info.getEntityCollection();
	            if (entities != null) {
	                entity = entities.getEntity(x, y);
	            }
	        }
	        ChartMouseEvent chartEvent = new ChartMouseEvent(getChart(), event,
	                entity);
	        for (int i = listeners.length - 1; i >= 0; i -= 1) {
	            ((MyChartMouseListener) listeners[i]).chartMouseReleased(chartEvent);
	        }
	}

}

 

把mousePressed和mouseReleased事件转发出来。

 扩展ChartMouseListener,增加这两个事件的出来接口:

import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;

public interface MyChartMouseListener extends ChartMouseListener {
	
	public void chartMousePressed(ChartMouseEvent event);
	public void chartMouseReleased(ChartMouseEvent event);
	
}

 实现自定义的MouseListener:

import java.awt.Cursor;
import java.awt.Shape;

import javax.swing.JPanel;

import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.data.xy.XYIntervalDataItem;
import org.jfree.data.xy.XYIntervalSeries;
import org.jfree.data.xy.XYIntervalSeriesCollection;

public class MyBarChartListener implements MyChartMouseListener {

	@Override
	public void chartMouseClicked(ChartMouseEvent event) {
		// TODO Auto-generated method stub
/*
		JFreeChart chart = event.getChart();

		if (chart == null)
			return;
		XYItemEntity ce = (XYItemEntity) event.getEntity();
		if (ce == null)
			return;
		IntervalXYDataset my = (IntervalXYDataset) ce.getDataset();

		int sindex = ce.getSeriesIndex();
		int iindex = ce.getItem();

		System.out.println("x = " + my.getXValue(sindex, iindex));
		System.out.println("y = " + my.getYValue(sindex, iindex));
*/
	}

	@Override
	public void chartMouseMoved(ChartMouseEvent event) {
		// TODO Auto-generated method stub

	}

	XYItemEntity ce;
	XYIntervalSeriesCollection my;

	@Override
	public void chartMousePressed(ChartMouseEvent event) {
		// TODO Auto-generated method stub
		System.out.println("mouse chartMousePressed");
		JPanel src = (JPanel) event.getTrigger().getSource();

		src.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		JFreeChart chart = event.getChart();

		if (chart == null)
			return;
		ce = (XYItemEntity) event.getEntity();
		if (ce == null)
			return;
		 my = (XYIntervalSeriesCollection) ce.getDataset();
		
		int sindex = ce.getSeriesIndex();
		int iindex = ce.getItem();
		
		Shape shape = ce.getArea();
		
	
		
		System.out.println("sindex = " + sindex);
		System.out.println("iindex = " + iindex);
		System.out.println("x = " + my.getXValue(sindex, iindex));
		System.out.println("y = " + my.getYValue(sindex, iindex));

		
		
		
		XYIntervalSeries series = (XYIntervalSeries) my.getSeries(ce.getSeriesIndex());
		
		System.out.println("y1 = " + shape.getBounds2D().getCenterY());
		

		
/*		series.remove(my.getXValue(sindex, iindex));
	
		Day day1 = new Day(13, 6, 2007);
	        Day day2 = new Day(14, 6, 2007);

		XYBarChartDemo7.addItem(series,day1,day2,sindex);
*/
	
	}

	@Override
	public void chartMouseReleased(ChartMouseEvent event) {
		// TODO Auto-generated method stub
		System.out.println("mouse chartMouseReleased");
		MyChartPanel src = (MyChartPanel) event.getTrigger().getSource();
		src.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
		
		double cursorY = event.getTrigger().getY();
		
		System.out.println("y = "+ cursorY);
		
		int seriesIndex = my.getSeriesCount();

		
		double maxY = src.getScreenDataArea().getMaxY();
		double minY = src.getScreenDataArea().getMinY();
		
		double heightY = (maxY-minY)/seriesIndex;
		
		for(int i=0;i<seriesIndex;i++)
		{
			if(cursorY >= minY && cursorY<=(i+1)*heightY)
			{
				XYIntervalSeries srcSeries =((XYIntervalSeriesCollection) (this.ce.getDataset())).getSeries(seriesIndex-i-1);
				
				XYIntervalSeriesCollection destSeriesCollection = (XYIntervalSeriesCollection) (this.ce.getDataset());
				XYIntervalSeries destSeries =destSeriesCollection.getSeries(this.ce.getSeriesIndex());
				XYIntervalDataItem item = (XYIntervalDataItem) destSeries.getDataItem(this.ce.getItem());			
				
				srcSeries.add(item.getX(), item.getXLowValue(), item.getXHighValue(), seriesIndex-i-1, seriesIndex-i-1-0.1, seriesIndex-i-1+0.3);
				destSeries.remove(destSeriesCollection.getXValue(this.ce.getSeriesIndex(), this.ce.getItem()));
/*				
				Day day1 = new Day(13, 6, 2007);
		        Day day2 = new Day(14, 6, 2007);

		        XYBarChartDemo7.addItem(series,day1,day2,seriesIndex-i-1);
*/		        
		        break;

			}
		}
		

	}

 

就可以实现在jfreechart中的图形的拖拽了。

 

   

你可能感兴趣的:(swing,jfreechart)