Problem with updating crosshair when using SWT

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
Worblehat
Posts: 7
Joined: Tue Jun 30, 2015 1:01 pm
antibot: No, of course not.

Problem with updating crosshair when using SWT

Post by Worblehat » Mon Aug 03, 2015 7:10 pm

Hello,

I got a problem regarding the crosshairs in a CombinedRangeXYPlot when using SWT. With Swing everything works fine. I boiled it down to a minimal example that shows the problem.
There are two source codes below. The first one uses Swing, the second one SWT. Apart from that they do the exact same thing.

There is a CombinedRangeXYPlot with two subplots. When the user clicks on the chart, the range crosshair of the second plot is set to the range crosshair value of the first plot:

Code: Select all

plot2.setRangeCrosshairValue(plot1.getRangeCrosshairValue());
So clicking in the first plots changes the crosshairs in both plots. To get the new crosshair values after a mouse click I use a combination of a ChartMouseListener and a ChartProgressListener as described here.

Problem with the SWT version:
The updating of the crosshair in plot2 is always delayed by one click. So it shows the value of the last but one click in plot1. Looks like the chart is not directly updated after the crosshair has been changed.

Any ideas how to fix this?

Swing:

Code: Select all

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.NumberAxis;
import org.jfree.chart.event.ChartProgressEvent;
import org.jfree.chart.event.ChartProgressListener;
import org.jfree.chart.plot.CombinedRangeXYPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.DefaultXYDataset;

import javax.swing.JFrame;

public class CombinedPlotCrosshairDemo {

    static XYPlot plot1;
    static XYPlot plot2;

    public static void main(String[] args) {

        DefaultXYDataset data = new DefaultXYDataset();
        data.addSeries(0, createData());

        plot1 = new XYPlot();
        plot1.setDomainAxis(new NumberAxis());
        plot1.setRenderer(0, new XYLineAndShapeRenderer());
        plot1.setDataset(0, data);
        plot1.setRangeCrosshairVisible(true);

        plot2 = new XYPlot();
        plot2.setDomainAxis(new NumberAxis());
        plot2.setRenderer(0, new XYLineAndShapeRenderer());
        plot2.setDataset(0, data);
        plot2.setRangeCrosshairVisible(true);

        CombinedRangeXYPlot combPlot = new CombinedRangeXYPlot();
        combPlot.setRangeAxis(new NumberAxis());
        combPlot.add(plot1);
        combPlot.add(plot2);

        JFreeChart chart = new JFreeChart(combPlot);
        ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new java.awt.Dimension(800, 600));

        JFrame frame = new JFrame();
        frame.setContentPane(chartPanel);
        frame.pack();
        frame.setVisible(true);

        CrosshairUpdater crosshairUpdater = new CrosshairUpdater();
        chart.addProgressListener(crosshairUpdater);
        chartPanel.addChartMouseListener(crosshairUpdater);
    }

    private static class CrosshairUpdater
            implements ChartMouseListener, ChartProgressListener {

        private ChartMouseEvent mouseEvent;

        @Override
        public void chartMouseClicked(ChartMouseEvent event) {
            mouseEvent = event;
        }

        @Override
        public void chartMouseMoved(ChartMouseEvent chartMouseEvent) {
        }

        @Override
        public void chartProgress(ChartProgressEvent event) {
            if (event.getType() == ChartProgressEvent.DRAWING_FINISHED
                    && mouseEvent != null) {
                plot2.setRangeCrosshairValue(plot1.getRangeCrosshairValue());
                mouseEvent = null;
            }
        }
    }

    private static double[][] createData() {
        double[][] data = new double[2][5];
        data[0][0] = 1;
        data[0][1] = 2;
        data[0][2] = 3;
        data[0][3] = 4;
        data[0][4] = 5;
        data[1][0] = 4;
        data[1][1] = 7;
        data[1][2] = 2;
        data[1][3] = 6;
        data[1][4] = 4;
        return data;
    }
}
SWT:

Code: Select all

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.event.ChartProgressEvent;
import org.jfree.chart.event.ChartProgressListener;
import org.jfree.chart.plot.CombinedRangeXYPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.experimental.chart.swt.ChartComposite;

public class CombinedPlotCrosshairDemoSWT {

    static XYPlot plot1;
    static XYPlot plot2;

    public static void main(String[] args) {

        DefaultXYDataset data = new DefaultXYDataset();
        data.addSeries(0, createData());

        plot1 = new XYPlot();
        plot1.setDomainAxis(new NumberAxis());
        plot1.setRenderer(0, new XYLineAndShapeRenderer());
        plot1.setDataset(0, data);
        plot1.setRangeCrosshairVisible(true);

        plot2 = new XYPlot();
        plot2.setDomainAxis(new NumberAxis());
        plot2.setRenderer(0, new XYLineAndShapeRenderer());
        plot2.setDataset(0, data);
        plot2.setRangeCrosshairVisible(true);

        CombinedRangeXYPlot combPlot = new CombinedRangeXYPlot();
        combPlot.setRangeAxis(new NumberAxis());
        combPlot.add(plot1);
        combPlot.add(plot2);

        JFreeChart chart = new JFreeChart(combPlot);
        Display display = new Display();
        Shell parent = new Shell(display);
        ChartComposite composite =
                new ChartComposite(parent, SWT.NONE, chart, true);

        CrosshairUpdater crosshairUpdater = new CrosshairUpdater();
        composite.addChartMouseListener(crosshairUpdater);
        chart.addProgressListener(crosshairUpdater);

        parent.setLayout(new FillLayout());
        parent.pack();
        parent.open();
        while (!parent.isDisposed()) {
            if (!display.readAndDispatch ()) {
                display.sleep();
            }
        }
        display.dispose();
    }

    private static class CrosshairUpdater
            implements ChartMouseListener, ChartProgressListener {

        private ChartMouseEvent mouseEvent;

        @Override
        public void chartMouseClicked(ChartMouseEvent event) {
            mouseEvent = event;
        }

        @Override
        public void chartMouseMoved(ChartMouseEvent chartMouseEvent) {
        }

        @Override
        public void chartProgress(ChartProgressEvent event) {
            if (event.getType() == ChartProgressEvent.DRAWING_FINISHED
                    && mouseEvent != null) {
                plot2.setRangeCrosshairValue(plot1.getRangeCrosshairValue());
                mouseEvent = null;
            }
        }
    }

    private static double[][] createData() {
        double[][] data = new double[2][5];
        data[0][0] = 1;
        data[0][1] = 2;
        data[0][2] = 3;
        data[0][3] = 4;
        data[0][4] = 5;
        data[1][0] = 4;
        data[1][1] = 7;
        data[1][2] = 2;
        data[1][3] = 6;
        data[1][4] = 4;
        return data;
    }
}

Locked