Search code examples
javaswingjfreechart

jFreechart points vanish when clicking


I have a Java 6/Swing application (yes, I know, but thats the requirement) and I need to show some polar plots. Everything works so far so good, but when I click on the plot, the plotted points vanish, even if I move the window around it might vanish. I work with netbeans, here is a dummy-code that causes the same issue

The libraries used are

  • jfreechart-1.0.19.jar
  • jcommon-1.0.23.jar

NewJFrame.java

import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;


public class NewJFrame extends javax.swing.JFrame {


    private PlotHandler plotHandler;

    public NewJFrame() {
        initComponents();
        plotHandler = new PlotHandler(jPanel1, "blub", 1);
    }


    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 504, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 409, Short.MAX_VALUE)
        );

        jButton1.setText("jButton1");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(36, Short.MAX_VALUE))
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(jButton1)
                .addGap(217, 217, 217))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(jButton1)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>                        

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        XYSeriesCollection data;
        XYSeries series;//("Bearing"+getBearingIndex(i));
        data = new XYSeriesCollection();
        series = new XYSeries("Bearings");
        series.add(Math.random()*180/Math.PI, 
            Math.random());
        data.addSeries(series);
        plotHandler.plotData(data);
    }                                        

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new NewJFrame().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton jButton1;
    private javax.swing.JPanel jPanel1;
    // End of variables declaration                   
}

PlotHandler.java

import java.awt.BorderLayout;
import javax.swing.JPanel;
import org.jfree.data.xy.XYSeriesCollection;

public class PlotHandler {
    private final JPanel jPanel;
    private final String plane;
    private double range;


    public PlotHandler(JPanel jPanel, String plane, double range) {
        this.jPanel = jPanel;
        this.plane = plane;
        this.range = range;

        // initialize plot
        this.jPanel.setLayout(new java.awt.BorderLayout());
        this.jPanel.add(PolarPlotHandler.emptyPolarChart(range), BorderLayout.CENTER);
        this.jPanel.validate();
    }

    public void plotData(XYSeriesCollection data) {
        jPanel.setLayout(new java.awt.BorderLayout());

        jPanel.add(PolarPlotHandler.createPolarChart(data, range), BorderLayout.CENTER);
        jPanel.validate();        
    }
}

PolarPlotHandler.java

import java.awt.Color;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.PolarChartPanel;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PolarPlot;
import org.jfree.chart.renderer.DefaultPolarItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeriesCollection;

public final class PolarPlotHandler  {

    private PolarPlotHandler() {  } 

    public static ChartPanel createPolarChart(XYSeriesCollection data, double range) {
        final XYDataset dataset = data;
        range = 200;
        range = Math.ceil(range/10)*10;
        range = Math.max(1, range);
        final JFreeChart chart = createChart(dataset, range/1000000);
        if(data.getSeriesCount()<=1 && data.getSeries(0).getItemCount()>0)
            chart.removeLegend();
        else {

        }
        ChartPanel chartPanel = new PolarChartPanel(chart);
        chartPanel.setDomainZoomable(false);
        chartPanel.setRangeZoomable(false);

        return chartPanel;
    }
    private static JFreeChart createChart(final XYDataset dataset, double range) {
        final JFreeChart chart = ChartFactory.createPolarChart(
                "", dataset, true, true, false
        );
        final PolarPlot plot = (PolarPlot) chart.getPlot();
        // get Axis
        plot.setAngleOffset(0);
        plot.setCounterClockwise(true);
        plot.getAxis().setTickLabelsVisible(false);
        plot.setAngleTickUnit(new NumberTickUnit(45));
        ((NumberAxis)plot.getAxis()).setTickUnit(new NumberTickUnit(range));
        // find the maximum range
        plot.getAxis().setRange(0, 2.0);
        plot.getAxis().setVisible(true);
        plot.setBackgroundAlpha(0.0f);
        plot.setAngleGridlinePaint(Color.black);
        plot.setRadiusGridlinePaint(Color.black);
        final DefaultPolarItemRenderer renderer = (DefaultPolarItemRenderer) plot.getRenderer();
        renderer.setSeriesFilled(2, false);
        return chart;
    }
public static ChartPanel emptyPolarChart() {
    return emptyPolarChart(200.0);
}

public static ChartPanel emptyPolarChart(double range) {
    final JFreeChart chart = createChart(new XYSeriesCollection(), range/1000000);
    chart.removeLegend();
    ChartPanel chartPanel = new PolarChartPanel(chart);
    return chartPanel;
}
}

Solution

  • It looks like you're trying to update a PolarPlot by replacing the entire, enclosing ChartPanel. Instead, update the dataset's series and the listening chart panel will update itself in response. In the example below, the button's handler clears the dataset's XYSeries and adds a new, random point each time the button is clicked.

    @Override
    public void actionPerformed(ActionEvent e) {
        series.clear();
        series.add(r.nextDouble() * 360, r.nextDouble());
    }
    

    image

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.FlowLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Random;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import org.jfree.chart.ChartFactory;
    import org.jfree.chart.ChartPanel;
    import org.jfree.chart.JFreeChart;
    import org.jfree.chart.plot.PolarPlot;
    import org.jfree.data.xy.XYDataset;
    import org.jfree.data.xy.XYSeries;
    import org.jfree.data.xy.XYSeriesCollection;
    
    /** @see http://stackoverflow.com/a/36846122/230513 */
    public class Test {
    
        private final XYSeries series = new XYSeries("Series");
        private final XYDataset dataset = new XYSeriesCollection(series);
    
        public Test() {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JFreeChart chart = ChartFactory.createPolarChart(
                "Title", dataset, true, true, false);
            final PolarPlot plot = (PolarPlot) chart.getPlot();
            plot.setBackgroundPaint(Color.white);
            plot.getAxis().setRange(0, 1);
            plot.getAxis().setTickLabelsVisible(false);
            plot.setAngleGridlinePaint(Color.black);
            plot.setRadiusGridlinePaint(Color.black);
            plot.setRadiusMinorGridlinesVisible(false);
            ChartPanel chartPanel = new ChartPanel(chart) {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(640, 480);
                }
            };
    
            JButton button = new JButton("Button");
            button.addActionListener(new ActionListener() {
                Random r = new Random();
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    series.clear();
                    series.add(r.nextDouble() * 360, r.nextDouble());
                }
            });
            JPanel control = new JPanel(new FlowLayout(FlowLayout.RIGHT));
            control.add(button);
    
            f.add(chartPanel, BorderLayout.CENTER);
            f.add(control, BorderLayout.SOUTH);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        }
    
        public static void main(String args[]) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    Test t = new Test();
                }
            });
        }
    }