JFreeChart:使用ChartMouseListener和鼠标移动在ChartPanel中进行动态点选择 [英] JFreeChart: Dynamic point selection in ChartPanel using ChartMouseListener and mouse move

查看:63
本文介绍了JFreeChart:使用ChartMouseListener和鼠标移动在ChartPanel中进行动态点选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用JFreeChart的图表,单击该图表后,将标记放置在相关位置(请参见下图).

我需要的不是在单击后而是在鼠标移动时更改位置.

我知道使用模块ChartMouseListener可以扩展其功能.

  ChartMouseListener l =新的ChartMouseListener(){@Overridepublic void chartMouseMoved(ChartMouseEvent e){int newX = e.getTrigger().getX();int newY = e.getTrigger().getY();System.out.println("chartMouseMoved to" + newX +" + newY);}@Overridepublic void chartMouseClicked(ChartMouseEvent e){}};chartPanel.addChartMouseListener(l); 

如何在图表中设置选定的轴?

 包org.jfree.chart.demo;导入java.awt.Color;导入java.text.SimpleDateFormat;导入javax.swing.JPanel;导入org.jfree.chart.ChartFactory;导入org.jfree.chart.ChartMouseEvent;导入org.jfree.chart.ChartMouseListener;导入org.jfree.chart.ChartPanel;导入org.jfree.chart.JFreeChart;导入org.jfree.chart.StandardChartTheme;导入org.jfree.chart.axis.DateAxis;导入org.jfree.chart.entity.XYItemEntity;导入org.jfree.chart.plot.XYPlot;导入org.jfree.chart.renderer.xy.XYItemRenderer;导入org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;导入org.jfree.data.time.Month;导入org.jfree.data.time.TimeSeries;导入org.jfree.data.time.TimeSeriesCollection;导入org.jfree.data.xy.XYDataset;导入org.jfree.ui.ApplicationFrame;导入org.jfree.ui.RectangleInsets;导入org.jfree.ui.RefineryUtilities;/***时间序列图的示例.在大多数情况下,默认设置为*使用,除了渲染器被修改为显示填充的形状(以及*行)在每个数据点.*/公共类TimeSeriesChartDemo1扩展了ApplicationFrame {私有静态最终长serialVersionUID = 1L;{//使用新的阴影生成器功能设置主题//1.0.14-为了向后兼容,默认情况下未启用图表工厂.setChartTheme(new StandardChartTheme("JFree/Shadow",true));}/***演示应用程序,显示如何创建简单的时间序列* 图表.本示例使用每月数据.** @参数标题*框架标题.*/public TimeSeriesChartDemo1(String title){超级(标题);ChartPanel chartPanel =(ChartPanel)createDemoPanel();chartPanel.setPreferredSize(new java.awt.Dimension(800,600));setContentPane(chartPanel);ChartMouseListener l =新的ChartMouseListener(){@Overridepublic void chartMouseMoved(ChartMouseEvent e){int newX = e.getTrigger().getX();int newY = e.getTrigger().getY();System.out.println("chartMouseMoved to" + newX +" + newY);}@Overridepublic void chartMouseClicked(ChartMouseEvent e){}};System.out.println(chartPanel.getMouseListeners()[0]);chartPanel.addChartMouseListener(l);}/***创建一个图表.** @param数据集*数据集.** @return图表.*/私人静态JFreeChart createChart(XYDataset数据集){JFreeChart图表= ChartFactory.createTimeSeriesChart(法律和一般单位信托价格",//标题"Date",//x轴标签每单位价格",//y轴标签数据集,//数据是,//创建图例?是,//生成工具提示?true//生成网址?);chart.setBackgroundPaint(Color.white);XYPlot plot =(XYPlot)chart.getPlot();plot.setBackgroundPaint(Color.lightGray);plot.setDomainGridlinePaint(Color.white);plot.setRangeGridlinePaint(Color.white);plot.setAxisOffset(new RectangleInsets(5.0,5.0,5.0,5.0));plot.setDomainCrosshairVisible(true);plot.setRangeCrosshairVisible(true);XYItemRenderer r = plot.getRenderer();if(r instanceof XYLineAndShapeRenderer){XYLineAndShapeRenderer渲染器=(XYLineAndShapeRenderer)r;renderer.setBaseShapesVisible(true);renderer.setBaseShapesFilled(true);renderer.setDrawSeriesLineAsPath(true);}DateAxis轴=(DateAxis)plot.getDomainAxis();axis.setDateFormatOverride(new SimpleDateFormat("MMM-yyyy"));;退货图表}/***创建一个数据集,该数据集由两个系列的每月数据组成.** @return数据集.*/私人静态XYDataset createDataset(){TimeSeries s1 =新的TimeSeries("L& G欧洲指数信托");s1.add(new Month(2,1),.8);s1.add(new Month(3,1),.3);s1.add(new Month(4,1),.8);s1.add(new Month(5,1),.6);s1.add(new Month(6,1),.8);s1.add(new Month(7,1),.3);s1.add(new Month(8,1),.9);s1.add(new Month(9,1),.7);s1.add(new Month(10,1),.2);s1.add(new Month(11,1),.8);s1.add(new Month(12,1),.6);s1.add(new Month(1,2),.9);s1.add(new Month(2,2),.7);s1.add(new Month(3,2),.3);s1.add(new Month(4,2),.9);s1.add(new Month(5,2),.8);s1.add(new Month(6,2),.0);s1.add(new Month(7,2),.8);TimeSeries s2 =新的TimeSeries("L& G英国指数信托");s2.add(new Month(2,1),.6);s2.add(new Month(3,1),.2);s2.add(new Month(4,1),.2);s2.add(new Month(5,1),.1);s2.add(new Month(6,1),.6);s2.add(new Month(7,1),.2);s2.add(new Month(8,1),.5);s2.add(new Month(9,1),.7);s2.add(new Month(10,1),.5);s2.add(new Month(11,1),.1);s2.add(new Month(12,1),.3);s2.add(new Month(1,2),.7);s2.add(new Month(2,2),.0);s2.add(new Month(3,2),.6);s2.add(new Month(4,2),.2);s2.add(new Month(5,2),.6);s2.add(new Month(6,2),.8);s2.add(new Month(7,2),.6);//**********************************************************************//JFreeChart包含了更多的演示应用程序//开发人员指南...有关更多信息,请参见:////>http://www.object-refinery.com/jfreechart/guide.html////**********************************************************************TimeSeriesCollection数据集= new TimeSeriesCollection();dataset.addSeries(s1);dataset.addSeries(s2);返回数据集;}/***为演示创建一个面板(由SuperDemo.java使用).** @return一个面板.*/公共静态JPanel createDemoPanel(){JFreeChart图表= createChart(createDataset());ChartPanel面板=新的ChartPanel(图表);panel.setFillZoomRectangle(true);panel.setMouseWheelEnabled(true);返回面板;}/***演示应用程序的起点.** @参数args*被忽略.*/公共静态void main(String [] args){TimeSeriesChartDemo1演示=新的TimeSeriesChartDemo1(时间序列图演示1");demo.pack();RefineryUtilities.centerFrameOnScreen(demo);demo.setVisible(true);}} 

解决方案

在JFreeChart中有两种绘制十字准线的方法.对于您给出的示例,十字线是作为图表的一部分绘制的,因此,每次十字线的位置发生变化时,都需要重新绘制图表.在鼠标移动事件上执行此操作效率不高.

一种替代方法是使用CrosshairOverlay类.这会将十字准线绘制为现有图表上的叠加图,从而避免了在十字准线值更改时重新绘制图表.对于您想做的事情,这将更好地工作.

JFreeChart开发人员指南(我们鼓励JFreeChart用户购买,以便他们可以在财务上帮助JFreeChart项目-只有很小的一部分,但这是人的本性)上提供了几个此功能的示例./p>

以下是示例之一:

 /* --------------------------* CrosshairOverlayDemo1.java* --------------------------*(C)Object Refinery Limited版权所有2003-2014.**/包演示;导入java.awt.BasicStroke;导入java.awt.BorderLayout;导入java.awt.Color;导入java.awt.geom.Rectangle2D;导入javax.swing.JFrame;导入javax.swing.JPanel;导入javax.swing.SwingUtilities;导入org.jfree.chart.ChartFactory;导入org.jfree.chart.ChartMouseEvent;导入org.jfree.chart.ChartMouseListener;导入org.jfree.chart.ChartPanel;导入org.jfree.chart.JFreeChart;导入org.jfree.chart.axis.ValueAxis;导入org.jfree.chart.panel.CrosshairOverlay;导入org.jfree.chart.plot.Crosshair;导入org.jfree.chart.plot.XYPlot;导入org.jfree.data.general.DatasetUtilities;导入org.jfree.data.xy.XYDataset;导入org.jfree.data.xy.XYSeries;导入org.jfree.data.xy.XYSeriesCollection;导入org.jfree.ui.RectangleEdge;/***演示显示跟随XYPlot数据点的十字准线的演示.*/公共类CrosshairOverlayDemo1扩展了JFrame {静态类MyDemoPanel扩展了JPanel实现的ChartMouseListener {私人ChartPanel chartPanel;私人十字准线x十字准线;私人十字准线y十字准线;公共MyDemoPanel(){超级(新的BorderLayout());JFreeChart图表= createChart(createDataset());this.chartPanel = new ChartPanel(chart);this.chartPanel.addChartMouseListener(this);CrosshairOverlay crosshairOverlay =新的CrosshairOverlay();this.xCrosshair =新的Crosshair(Double.NaN,Color.GRAY,新的BasicStroke(0f));this.xCrosshair.setLabelVisible(true);this.yCrosshair =新的Crosshair(Double.NaN,Color.GRAY,新的BasicStroke(0f));this.yCrosshair.setLabelVisible(true);crosshairOverlay.addDomainCrosshair(xCrosshair);crosshairOverlay.addRangeCrosshair(yCrosshair);this.chartPanel.addOverlay(crosshairOverlay);添加(this.chartPanel);}私人JFreeChart createChart(XYDataset数据集){JFreeChart图表= ChartFactory.createXYLineChart("CrosshairOverlayDemo1","X","Y",数据集);退货图表}私人XYDataset createDataset(){XYSeries series =新的XYSeries("S1");for(int x = 0; x< 10; x ++){series.add(x,x + Math.random()* 4.0);}XYSeriesCollection数据集=新的XYSeriesCollection(系列);返回数据集;}@Overridepublic void chartMouseClicked(ChartMouseEvent event){//忽略}@Overridepublic void chartMouseMoved(ChartMouseEvent event){Rectangle2D dataArea = this.chartPanel.getScreenDataArea();JFreeChart图表= event.getChart();XYPlot plot =(XYPlot)chart.getPlot();ValueAxis xAxis = plot.getDomainAxis();double x = xAxis.java2DToValue(event.getTrigger().getX(),dataArea,RectangleEdge.BOTTOM);//如果鼠标不在范围内,则使十字准线消失如果(!xAxis.getRange().包含(x)){x = Double.NaN;}双重y = DatasetUtilities.findYValue(plot.getDataset(),0,x);this.xCrosshair.setValue(x);this.yCrosshair.setValue(y);}}public CrosshairOverlayDemo1(字符串标题){超级(标题);setContentPane(createDemoPanel());}/***为演示创建一个面板(由SuperDemo.java使用).** @return一个面板.*/公共静态JPanel createDemoPanel(){返回新的MyDemoPanel();}公共静态void main(String [] args){SwingUtilities.invokeLater(new Runnable(){@Override公共无效run(){CrosshairOverlayDemo1应用=新的CrosshairOverlayDemo1("JFreeChart:CrosshairOverlayDemo1.java");app.pack();app.setVisible(true);}});}} 

I have a chart using JFreeChart where after click it put the markers on a related position (see figure below).

What I need is to change the position not after click but on mouse move.

I know that using a module ChartMouseListener I can extend its functionlity.

    ChartMouseListener l = new ChartMouseListener() {
        @Override
        public void chartMouseMoved(ChartMouseEvent e) {
            int newX = e.getTrigger().getX();
            int newY = e.getTrigger().getY();
            System.out.println("chartMouseMoved to " + newX + " " + newY);
        }
        @Override
        public void chartMouseClicked(ChartMouseEvent e) {
        }
    };
    chartPanel.addChartMouseListener(l);

How to set the selected axis in the chart?

    package org.jfree.chart.demo;

    import java.awt.Color;
    import java.text.SimpleDateFormat;

    import javax.swing.JPanel;

    import org.jfree.chart.ChartFactory;
    import org.jfree.chart.ChartMouseEvent;
    import org.jfree.chart.ChartMouseListener;
    import org.jfree.chart.ChartPanel;
    import org.jfree.chart.JFreeChart;
    import org.jfree.chart.StandardChartTheme;
    import org.jfree.chart.axis.DateAxis;
    import org.jfree.chart.entity.XYItemEntity;
    import org.jfree.chart.plot.XYPlot;
    import org.jfree.chart.renderer.xy.XYItemRenderer;
    import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
    import org.jfree.data.time.Month;
    import org.jfree.data.time.TimeSeries;
    import org.jfree.data.time.TimeSeriesCollection;
    import org.jfree.data.xy.XYDataset;
    import org.jfree.ui.ApplicationFrame;
    import org.jfree.ui.RectangleInsets;
    import org.jfree.ui.RefineryUtilities;

    /**
     * An example of a time series chart. For the most part, default settings are
     * used, except that the renderer is modified to show filled shapes (as well as
     * lines) at each data point.
     */
    public class TimeSeriesChartDemo1 extends ApplicationFrame {

        private static final long serialVersionUID = 1L;

        {
            // set a theme using the new shadow generator feature available in
            // 1.0.14 - for backwards compatibility it is not enabled by default
            ChartFactory
                    .setChartTheme(new StandardChartTheme("JFree/Shadow", true));
        }

        /**
         * A demonstration application showing how to create a simple time series
         * chart. This example uses monthly data.
         * 
         * @param title
         *            the frame title.
         */
        public TimeSeriesChartDemo1(String title) {
            super(title);
            ChartPanel chartPanel = (ChartPanel) createDemoPanel();
            chartPanel.setPreferredSize(new java.awt.Dimension(800, 600));
            setContentPane(chartPanel);
            ChartMouseListener l = new ChartMouseListener() {
                @Override
                public void chartMouseMoved(ChartMouseEvent e) {
                    int newX = e.getTrigger().getX();
                    int newY = e.getTrigger().getY();
                    System.out.println("chartMouseMoved to " + newX + " " + newY);
                }
                @Override
                public void chartMouseClicked(ChartMouseEvent e) {
                }
            };
            System.out.println(chartPanel.getMouseListeners()[0]);
            chartPanel.addChartMouseListener(l);
        }

        /**
         * Creates a chart.
         * 
         * @param dataset
         *            a dataset.
         * 
         * @return A chart.
         */
        private static JFreeChart createChart(XYDataset dataset) {

            JFreeChart chart = ChartFactory.createTimeSeriesChart(
                    "Legal & General Unit Trust Prices", // title
                    "Date", // x-axis label
                    "Price Per Unit", // y-axis label
                    dataset, // data
                    true, // create legend?
                    true, // generate tooltips?
                    true // generate URLs?
                    );

            chart.setBackgroundPaint(Color.white);

            XYPlot plot = (XYPlot) chart.getPlot();
            plot.setBackgroundPaint(Color.lightGray);
            plot.setDomainGridlinePaint(Color.white);
            plot.setRangeGridlinePaint(Color.white);
            plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
            plot.setDomainCrosshairVisible(true);
            plot.setRangeCrosshairVisible(true);

            XYItemRenderer r = plot.getRenderer();
            if (r instanceof XYLineAndShapeRenderer) {
                XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;
                renderer.setBaseShapesVisible(true);
                renderer.setBaseShapesFilled(true);
                renderer.setDrawSeriesLineAsPath(true);
            }

            DateAxis axis = (DateAxis) plot.getDomainAxis();
            axis.setDateFormatOverride(new SimpleDateFormat("MMM-yyyy"));

            return chart;

        }

        /**
         * Creates a dataset, consisting of two series of monthly data.
         * 
         * @return The dataset.
         */
        private static XYDataset createDataset() {

            TimeSeries s1 = new TimeSeries("L&G European Index Trust");
            s1.add(new Month(2, 1), .8);
            s1.add(new Month(3, 1), .3);
            s1.add(new Month(4, 1), .8);
            s1.add(new Month(5, 1), .6);
            s1.add(new Month(6, 1), .8);
            s1.add(new Month(7, 1), .3);
            s1.add(new Month(8, 1), .9);
            s1.add(new Month(9, 1), .7);
            s1.add(new Month(10, 1), .2);
            s1.add(new Month(11, 1), .8);
            s1.add(new Month(12, 1), .6);
            s1.add(new Month(1, 2), .9);
            s1.add(new Month(2, 2), .7);
            s1.add(new Month(3, 2), .3);
            s1.add(new Month(4, 2), .9);
            s1.add(new Month(5, 2), .8);
            s1.add(new Month(6, 2), .0);
            s1.add(new Month(7, 2), .8);

            TimeSeries s2 = new TimeSeries("L&G UK Index Trust");
            s2.add(new Month(2, 1), .6);
            s2.add(new Month(3, 1), .2);
            s2.add(new Month(4, 1), .2);
            s2.add(new Month(5, 1), .1);
            s2.add(new Month(6, 1), .6);
            s2.add(new Month(7, 1), .2);
            s2.add(new Month(8, 1), .5);
            s2.add(new Month(9, 1), .7);
            s2.add(new Month(10, 1), .5);
            s2.add(new Month(11, 1), .1);
            s2.add(new Month(12, 1), .3);
            s2.add(new Month(1, 2), .7);
            s2.add(new Month(2, 2), .0);
            s2.add(new Month(3, 2), .6);
            s2.add(new Month(4, 2), .2);
            s2.add(new Month(5, 2), .6);
            s2.add(new Month(6, 2), .8);
            s2.add(new Month(7, 2), .6);

            // ******************************************************************
            // More than demo applications are included with the JFreeChart
            // Developer Guide...for more information, see:
            //
            // > http://www.object-refinery.com/jfreechart/guide.html
            //
            // ******************************************************************

            TimeSeriesCollection dataset = new TimeSeriesCollection();
            dataset.addSeries(s1);
            dataset.addSeries(s2);

            return dataset;

        }

        /**
         * Creates a panel for the demo (used by SuperDemo.java).
         * 
         * @return A panel.
         */
        public static JPanel createDemoPanel() {
            JFreeChart chart = createChart(createDataset());
            ChartPanel panel = new ChartPanel(chart);
            panel.setFillZoomRectangle(true);
            panel.setMouseWheelEnabled(true);
            return panel;
        }

        /**
         * Starting point for the demonstration application.
         * 
         * @param args
         *            ignored.
         */
        public static void main(String[] args) {

            TimeSeriesChartDemo1 demo = new TimeSeriesChartDemo1(
                    "Time Series Chart Demo 1");
            demo.pack();
            RefineryUtilities.centerFrameOnScreen(demo);
            demo.setVisible(true);

        }

    }

解决方案

There are a couple of ways to draw crosshairs in JFreeChart. For the example you've given, the crosshairs are drawn as part of the chart, so each time the position of the crosshairs changes, the chart needs to be redrawn. Doing that on a mouse move event isn't going to be very efficient.

An alternative is to use the CrosshairOverlay class. This draws crosshairs as an overlay on an existing chart, which avoids the need to redraw the chart when the crosshair values change. That's going to work better for what you want to do.

There are a couple of examples of this feature included with the JFreeChart Developer Guide (which we encourage JFreeChart users to buy, so they can help the JFreeChart project financially - only a very small percentage do, but that's human nature).

Here is one of the examples:

/* --------------------------
 * CrosshairOverlayDemo1.java
 * --------------------------
 * (C) Copyright 2003-2014, by Object Refinery Limited.
 *
 */

package demo;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.panel.CrosshairOverlay;
import org.jfree.chart.plot.Crosshair;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleEdge;

/**
 * A demo showing crosshairs that follow the data points on an XYPlot.
 */
public class CrosshairOverlayDemo1 extends JFrame {

    static class MyDemoPanel extends JPanel implements ChartMouseListener {

        private ChartPanel chartPanel;

        private Crosshair xCrosshair;

        private Crosshair yCrosshair;

        public MyDemoPanel() {
            super(new BorderLayout());
            JFreeChart chart = createChart(createDataset());
            this.chartPanel = new ChartPanel(chart);
            this.chartPanel.addChartMouseListener(this);
            CrosshairOverlay crosshairOverlay = new CrosshairOverlay();
            this.xCrosshair = new Crosshair(Double.NaN, Color.GRAY, 
                    new BasicStroke(0f));
            this.xCrosshair.setLabelVisible(true);
            this.yCrosshair = new Crosshair(Double.NaN, Color.GRAY, 
                    new BasicStroke(0f));
            this.yCrosshair.setLabelVisible(true);
            crosshairOverlay.addDomainCrosshair(xCrosshair);
            crosshairOverlay.addRangeCrosshair(yCrosshair);
            this.chartPanel.addOverlay(crosshairOverlay);
            add(this.chartPanel);
        }

        private JFreeChart createChart(XYDataset dataset) {
            JFreeChart chart = ChartFactory.createXYLineChart(
                    "CrosshairOverlayDemo1", "X", "Y", dataset);
            return chart;
        }

        private XYDataset createDataset() {
            XYSeries series = new XYSeries("S1");
            for (int x = 0; x < 10; x++) {
                series.add(x, x + Math.random() * 4.0);
            }
            XYSeriesCollection dataset = new XYSeriesCollection(series);
            return dataset;
        }

        @Override
        public void chartMouseClicked(ChartMouseEvent event) {
            // ignore
        }

        @Override
        public void chartMouseMoved(ChartMouseEvent event) {
            Rectangle2D dataArea = this.chartPanel.getScreenDataArea();
            JFreeChart chart = event.getChart();
            XYPlot plot = (XYPlot) chart.getPlot();
            ValueAxis xAxis = plot.getDomainAxis();
            double x = xAxis.java2DToValue(event.getTrigger().getX(), dataArea, 
                    RectangleEdge.BOTTOM);
            // make the crosshairs disappear if the mouse is out of range
            if (!xAxis.getRange().contains(x)) { 
                x = Double.NaN;                  
            }
            double y = DatasetUtilities.findYValue(plot.getDataset(), 0, x);
            this.xCrosshair.setValue(x);
            this.yCrosshair.setValue(y);
        }  

    }

    public CrosshairOverlayDemo1(String title) {
        super(title);
        setContentPane(createDemoPanel());
    }

    /**
     * Creates a panel for the demo (used by SuperDemo.java).
     *
     * @return A panel.
     */
    public static JPanel createDemoPanel() {
        return new MyDemoPanel();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                CrosshairOverlayDemo1 app = new CrosshairOverlayDemo1(
                        "JFreeChart: CrosshairOverlayDemo1.java");
                app.pack();
                app.setVisible(true);
            }
        });
    }

}

这篇关于JFreeChart:使用ChartMouseListener和鼠标移动在ChartPanel中进行动态点选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆