How to over write paintComponent and keep chart zoomable?

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
antbegone
Posts: 5
Joined: Thu Aug 06, 2009 9:22 pm
antibot: No, of course not.

How to over write paintComponent and keep chart zoomable?

Post by antbegone » Thu Oct 22, 2009 5:12 pm

Hi, Gentlepersons,
I need to 'click on the chart to switch drawing a different dataset'.
I overwrite paintComponent, and install mouseListener.
The click-switch does work. However, I lost zoom capability.

Can you help? either what is wrong with the following, or
what is the correct way to achieve this.
Thanks
=================

Code: Select all

  
   public ChartPanel getPanel() {
       ChartPanel pnl = new ChartPanel(createChart()) {
          public void paintComponent(Graphics g) {
             super.paintComponent(g);
             if (chart == null) {
                return;
             }
             Graphics2D g2 = (Graphics2D) g.create();
             Dimension size = getSize();
             Rectangle2D whole = new Rectangle2D.Double();
             whole.setRect(0, 0, size.getWidth(), size.getHeight());
             chart.draw(g2, whole);                                   
          }
       };
          
       pnl.addChartMouseListener(new ChartMouseListener() {
          public void chartMouseClicked(ChartMouseEvent arg0) {
             chart = createChart();         
          }
          public void chartMouseMoved(ChartMouseEvent arg0) {   
          }
       });
                 
       pnl.setMouseZoomable(true);
       return pnl;
    }

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: How to over write paintComponent and keep chart zoomable?

Post by david.gilbert » Thu Oct 22, 2009 8:45 pm

There is some code in the paintComponent method that displays the zooming area...So if you override paintComponent it won't work correctly anymore. :shock:
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

antbegone
Posts: 5
Joined: Thu Aug 06, 2009 9:22 pm
antibot: No, of course not.

Re: How to over write paintComponent and keep chart zoomable?

Post by antbegone » Thu Oct 22, 2009 10:54 pm

Thanks David,

I attached a simple example here.
I can zoom as long as I do not click (to switch to the dataset B).
The paintComponent gets called even if I do not click.
if I click even once, the zoom does not work any more.

If I can not overwrite paintComponent, what is the best way
to achieve 'click and switch dataset'?

Thanks
===============

Code: Select all

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

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.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYErrorRenderer;
import org.jfree.data.xy.XYIntervalSeries;
import org.jfree.data.xy.XYIntervalSeriesCollection;

public class SwitchAB {

    private XYIntervalSeriesCollection dataset1 = new XYIntervalSeriesCollection();

   private XYIntervalSeriesCollection dataset2 = new XYIntervalSeriesCollection();

   private XYPlot plot = null;
   JFreeChart chart = null;
   private boolean isA = false;

   public SwitchAB() {
   }

   public JFreeChart createChart() {

      XYErrorRenderer renderer = new XYErrorRenderer();

      NumberAxis rangeAxisX = new NumberAxis("X");
      NumberAxis rangeAxisY = new NumberAxis("Y");
      plot = new XYPlot(null, rangeAxisX, rangeAxisY, null);
      plot.setRenderer(renderer);
      String tp = "";
      if (isA) {
         tp = "A";
         plot.setDataset(dataset1);
      }
      else {
         tp = "B";
         plot.setDataset(dataset2);
      }
      // System.err.println("tp=" + tp);
      chart = new JFreeChart(tp, plot);
      chart.setBackgroundPaint(Color.white);

      return chart;
   }

   public ChartPanel getPanel() {

      ChartPanel pnl = new ChartPanel(createChart()) {
         
         public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (chart == null) {
               return;
            }
            Graphics2D g2 = (Graphics2D) g.create();
            Dimension size = getSize();

            Rectangle2D whole = new Rectangle2D.Double();
            whole.setRect(0, 0, size.getWidth(), size.getHeight());

            chart.draw(g2, whole);
            System.err.println("paintComponent");
        
         }
      };


      pnl.addChartMouseListener(new ChartMouseListener() {    
         public void chartMouseClicked(ChartMouseEvent arg0) {
            int seriesCount = dataset1.getSeriesCount();
            if (seriesCount > 0) {
               // System.err.println("switch data set A/B");
               isA = !isA;
               chart = createChart();
            }
            else {
               isA = false;
            }
         }
         public void chartMouseMoved(ChartMouseEvent arg0) {
         }

      });
 
      pnl.setMouseZoomable(true, false);
      return pnl;
   }
   
   public static void main(String[] args) {

      JFrame frm = new JFrame();
      frm.setTitle("Switch AB");
      frm.setSize(new Dimension(400, 300));

      SwitchAB switchAB = new SwitchAB();

      XYIntervalSeries a = new XYIntervalSeries("A", false, true);
      a.add(1, 0.9, 1.1, 2, 1.8, 2.3);
      switchAB.dataset1.addSeries(a);

      XYIntervalSeries b = new XYIntervalSeries("B", false, true);
      b.add(4, 3.9, 4.1, 7, 6.8, 7.3);
      switchAB.dataset2.addSeries(b);

      frm.getContentPane().add(switchAB.getPanel());
      frm.setVisible(true);
   }

}



paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Re: How to over write paintComponent and keep chart zoomable?

Post by paradoxoff » Sat Oct 24, 2009 11:04 am

That was a tricky one.
You construct your ChartPanel with the JFreeChart object returned from the first invocation of createChart(). However, in your overridden paintComponent(...) method, you are using that JFreeChart object which is referenced by the "chart" variable of your SwitchAB class. This is not an issue as long as these objects are the same (not "equal" but "the same").
When you first click, you are calling createChart() again (which, btw, is unnecessary. You only need to exchange the datasets. There is no need to construct anything "new") and construct a new JFreeChart which is now referenced by the "chart" variable of your SwitchAB class, and the ChartPanel is now drawing a different chart than before. However, the chart panel method which is carrying out the zoom is not accessing the new chart objectm but the old one that was used to construct the ChartPanel, and is changing the zoom of the old chart. You do not see this, because the old chart is never drawn.
Here is a better approach:

Code: Select all

import java.awt.Color;
import java.awt.Font;
import java.awt.geom.*;
import javax.swing.*;
import java.io.*;
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.annotations.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.entity.*;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.chart.title.*;
import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.ui.RectangleEdge;

public class ChangeDatasetDemo implements ChartMouseListener{
	private DefaultXYDataset dataset1;
	private DefaultXYDataset dataset2;
	private XYPlot plot;
	private JFreeChart chart;
	private boolean isA = true;
		
	public ChangeDatasetDemo(){
		dataset1 = new DefaultXYDataset();
		dataset1.addSeries("Small Values",new double[][]{{1, 2, 3,4}, {5, 1, 7, 3}});		
		dataset2 = new DefaultXYDataset();
		dataset2.addSeries("Large Values",new double[][]{{100, 200, 300, 400}, {100, 800, 300, 600}});		
		ValueAxis xAxis = new NumberAxis("x");
		ValueAxis yAxis = new NumberAxis("y");
		XYItemRenderer renderer = new XYLineAndShapeRenderer();
		renderer.setSeriesPaint(0, Color.RED);
		renderer.setSeriesShape(0, new Ellipse2D.Double(-5, -5, 10, 10));
		plot = new XYPlot(dataset1, xAxis, yAxis, renderer);
		chart = new JFreeChart("XYPlot Demo", new Font("Tahoma", 2, 18), plot, true);
		JFrame frame = new JFrame("XY Plot Demo");
		ChartPanel cPanel = new ChartPanel(chart);
		cPanel.addChartMouseListener(this);
		frame.getContentPane().add(cPanel);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.pack();
		frame.setVisible(true);
	}
	public void chartMouseClicked(ChartMouseEvent e){
		isA = !isA;
		if(isA){
			plot.setDataset(dataset1);
			chart.getTitle().setText("A");
		}
		else{
			plot.setDataset(dataset2);
			chart.getTitle().setText("B");
		}
	}
	public void chartMouseMoved(ChartMouseEvent e){
	}
	public static void main(String[] args) {
		ChangeDatasetDemo demo = new ChangeDatasetDemo();	
	}
}

antbegone
Posts: 5
Joined: Thu Aug 06, 2009 9:22 pm
antibot: No, of course not.

Re: How to over write paintComponent and keep chart zoomable?

Post by antbegone » Wed Oct 28, 2009 4:11 pm

Thanks, paradoxoff,

I have not got time to try your example. I trust it will work
because (1) your analysis is right on the spot, I know I did
it in a tricky way and could not find a easy workaround; (2)
I saw your other posts that made good sense.

I will let you know if it works or bug you again if it does not work.

Locked