1

I wrote a simple parabola plot using JFreeChart. I get graphic point coordinates, when mouse button pressed and i also want to get graphic point coordinates, when mouse button released. But chartMouseMoved don't work while mouse button pressing. How can I solve my problem and get graphic coordinates after mouse button releasing?

This is my code:

package parabolademo;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

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.entity.ChartEntity;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.function.Function2D;
import org.jfree.data.function.PolynomialFunction2D;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;


public class ParabolaDemo extends ApplicationFrame {

    /*
     * @param title  the frame title.
     */
    int flag = 0;
    double delta = 0;
    double px = 0.0, py = 0.0, prx = 0.0, pry = 0.0, chartpx = 0.0, chartpy = 0.0, 
            chartX = 0.0, chartY = 0.0;
    int windowheight = 270;
    public ParabolaDemo(final String title) {

        super(title);
        double[] a = {0.0, 0.0, 1.0};
        Function2D p = new PolynomialFunction2D(a);
        double lrange = -20.0;
        double rrange = 20.0;
        XYDataset dataset = DatasetUtilities.sampleFunction2D(p, lrange, rrange, 1000, "y = f(x)");
        double max = 0.0;

        if (a[2] < 0) {
            max = p.getValue(-a[1] / 2*a[2]);
        }
        else {
            if (p.getValue(lrange) > p.getValue(rrange))
                max = p.getValue(lrange);
            else
                max = p.getValue(rrange);
        }
        System.out.println("max = " + max);
        delta = max / 16.4;

        final JFreeChart chart = ChartFactory.createXYLineChart(
            "Parabola",
            "X", 
            "Y", 
            dataset,
            PlotOrientation.VERTICAL,
            true,
            true,
            false
        );

        final ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.addMouseListener(new CustomListener());
        chartPanel.addChartMouseListener(new ChartMouseListener() {

            @Override
            public void chartMouseClicked(ChartMouseEvent cme) {

            }

            @Override
            public void chartMouseMoved(ChartMouseEvent cme) {
                ChartEntity ce = cme.getEntity();
                if (ce instanceof XYItemEntity) {
                    XYItemEntity e = (XYItemEntity) ce;
                    XYDataset d = ((XYItemEntity) ce).getDataset();
                    int i = ((XYItemEntity) ce).getItem();
                    chartpx = d.getXValue(0, i);
                    chartpy = d.getYValue(0, i);
                    //System.out.println("X:" + chartpx + ", Y:" + chartpy);
                }
                Point2D po = chartPanel.translateScreenToJava2D(cme.getTrigger().getPoint());
                Rectangle2D plotArea = chartPanel.getScreenDataArea();
                XYPlot plot = (XYPlot) chart.getPlot(); // your plot
                chartX = plot.getDomainAxis().java2DToValue(po.getX(), plotArea, plot.getDomainAxisEdge());
                chartY = plot.getRangeAxis().java2DToValue(po.getY(), plotArea, plot.getRangeAxisEdge());
                System.out.println("X:" + chartX + ", Y:" + chartY);
            }
        });
        chartPanel.setPreferredSize(new java.awt.Dimension(500, windowheight));
        chartPanel.setDomainZoomable(false);
        chartPanel.setRangeZoomable(false);
        setContentPane(chartPanel);
    }

    public static void main(final String[] args) {

        final ParabolaDemo demo = new ParabolaDemo("Parabola Plot Demo");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }


    public class CustomListener implements MouseListener {

          public void mouseClicked(MouseEvent e) {

          }

          public void mouseEntered(MouseEvent e) {

          }

          public void mouseExited(MouseEvent e) {

          }

          public void mousePressed(MouseEvent e) {
              flag = 1;
              px = chartpx;
              py = chartpy;
              System.out.println("Mouse Pressed! xpos = " + px + "; py = " + py);
          }

          public void mouseReleased(MouseEvent e) {
              flag = 1;
              prx = chartX;
              pry = chartY;
              System.out.println("Mouse Released! xpos = " + prx + "; py = " + pry);
          }
     }
}

Thanks in advance!

Denis
  • 503
  • 8
  • 32

1 Answers1

5

As shown here, ChartPanel uses the click-drag-release gesture to handle zooming; setMouseZoomable(false) doesn't change that.

Working from the suggestion shown here, the complete example below prints the coordinates of any clicked point. I've enlarged the series shape to make it easier to see the effect. In addition, Swing GUI objects should be constructed and manipulated only on the event dispatch thread.

image

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Rectangle;
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.entity.ChartEntity;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.function.Function2D;
import org.jfree.data.function.PolynomialFunction2D;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import org.jfree.util.ShapeUtilities;

public class ParabolaDemo extends ApplicationFrame {

    /*
     * @see https://stackoverflow.com/a/20107935/230513
     * @see https://stackoverflow.com/q/20081801/230513
     */
    public ParabolaDemo(final String title) {

        super(title);
        double[] a = {0.0, 0.0, 3.0};
        Function2D p = new PolynomialFunction2D(a);
        XYDataset dataset = DatasetUtilities.sampleFunction2D(
            p, -20.0, 20.0, 20, "y = 3x² {-20…20}");
        final JFreeChart chart = ChartFactory.createXYLineChart("Parabola",
            "X", "Y", dataset, PlotOrientation.VERTICAL, true, true, false);
        final XYPlot plot = (XYPlot) chart.getPlot();
        XYLineAndShapeRenderer r = (XYLineAndShapeRenderer) plot.getRenderer();
        r.setBaseShapesVisible(true);
        r.setSeriesShape(0, ShapeUtilities.createTranslatedShape(
            new Rectangle(12, 12), -6, -6));
        final ChartPanel chartPanel = new ChartPanel(chart) {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(640, 480);
            }
        };
        chartPanel.addChartMouseListener(new ChartMouseListener() {

            @Override
            public void chartMouseClicked(ChartMouseEvent cme) {
                report(cme);
            }

            @Override
            public void chartMouseMoved(ChartMouseEvent cme) {
                //report(cme);
            }

            private void report(ChartMouseEvent cme) {
                ChartEntity ce = cme.getEntity();
                if (ce instanceof XYItemEntity) {
                    XYItemEntity e = (XYItemEntity) ce;
                    XYDataset d = e.getDataset();
                    int s = e.getSeriesIndex();
                    int i = e.getItem();
                    System.out.println("X:" + d.getX(s, i) + ", Y:" + d.getY(s, i));
                }
            }
        });
        setContentPane(chartPanel);
    }

    public static void main(final String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                final ParabolaDemo demo = new ParabolaDemo("Parabola Demo");
                demo.pack();
                RefineryUtilities.centerFrameOnScreen(demo);
                demo.setVisible(true);
            }
        });
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • thanks for code, I wanted a little another. I want to make the editor of polynomials for the program. For example, for parabola creation it is enough to know 3 points (let it is points of p1, p2, p3). We take p1 point, we clamp it and we move on the plane. As p2 and p3 are known, we also can build up again a parabola, knowing new coordinates of a point of p1 and old coordinates of p2 and p3. But it is impossible to learn new coordinates for me for p1 (mouselistener doesn't work when the mouse button is clamped, and the mouse moves on the plane). how it is possible to learn new coordinates? – Denis Nov 21 '13 at 15:08
  • I've not done anything like that with `JFreeChart`, but using an adjacent control may be an option; some examples using `JSlider` are seen [here](http://stackoverflow.com/search?tab=votes&q=user%3a230513%20%5bjfreechart%5d%20jslider). – trashgod Nov 21 '13 at 19:14
  • I think you would need to override the mouse motion listener methods in `ChartPanel` with your own. – trashgod Nov 25 '13 at 14:02