How to use JFreeChart with SWT (includes sample code)

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Robert Gash

How to use JFreeChart with SWT (includes sample code)

Post by Robert Gash » Wed Jul 09, 2003 7:32 pm

I have seen a number of posts asking how to use JFreeChart within SWT applications. Most solutions appear to rely on converting AWT Image's into SWT Image's. That process works fine, but seems overly tiedious.

Newer SWT implementations are beginning to provide very rough wrappers around a java.awt.Panel that allow older AWT/Swing components to be reused inside of SWT applications. Currently only Win32 platforms are supported, although I imagine that other ports aren't far off.

Here's a quick and dirty example of how to use JFreeChart "natively" (without converting Images, etc.) inside of your Win32 SWT application. This has been tested on the Eclipse 3.0M1 SWT drop (build 3007). This WILL NOT work with older 2.x SWT drops.

0) Take a look at

Code: Select all

org.eclipse.swt.internal.SWT_AWT
, all of the functionality to create a Panel backed by our Composite resides here in the

Code: Select all

new_Panel
method.

1) Create a simple SWT Composite that will contain your AWT/Swing components (in this case a ChartPanel). Align the Composite using your usual SWT layout managers.

2) Create a JFreeChart based on your data using the usual ChartFactory methods.

3) Create a new java.awt.Panel that is backed by your SWT Composite. Optionally you may wish to set the background color to that of the composite and add a layout manager if you want to have several JFreeChart's in the same Composite, or you want the chart to resize itself based on the size of the SWT Composite.

4) Create ChartPanel's and add them to your java.awt.Panel that you obtained from SWT_AWT in step 3.

5) Sit back and enjoy!

Sounds easy, doesn't it? Here's the code (tested using SWT 3.0M1, JFreeChart 0.9.8, JCommon 0.8.3, J2SDK 1.4.2 on Win32 [Win2k]).

Code: Select all

/// STEP 1 ////////////////////////////////////////////////
// create a composite suitable for displaying all of our chart data
Composite chartComposite = new Composite(/* options */);
chartComposite.setLayoutData(/* set the layout options */);

/// STEP 2 ////////////////////////////////////////////////
// create the dataset for the pie chart of the distribution
DefaultPieDataset pieData = new DefaultPieDataset();
/* populate the pieData here */

JFreeChart chart = ChartFactory.createPie3DChart(/* some options */);
// OPTIONAL: tinkering with plot options here

/// STEP 3 ////////////////////////////////////////////////
// Grab the background color from the SWT Composite
// so our AWT panel "matches" the SWT Composite
Color backgroundColor = chartComposite.getBackground();

// create the panel
Panel chartPanel = SWT_AWT.new_Panel(chartComposite);

// set the panel's background (defaults to pure white)
chartPanel.setBackground(new java.awt.Color(backgroundColor.getRed(),
                                                    backgroundColor.getGreen(),
                                                    backgroundColor.getBlue()));
// set the AWT layout manager
chartPanel.setLayout(/* some AWT/Swing layout manager like BoxLayout */);

/// STEP 4 ////////////////////////////////////////////////        
ChartPanel jfreeChartPanel = new ChartPanel(chart);
chartPanel.add(jfreeChartPanel);
-Robert Gash, Software Developer, Enkia Corporation
gashalot <at> enkia.com

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

Post by david.gilbert » Thu Jul 10, 2003 8:21 am

Hi Robert,

Thanks for your post. I get the occasional question about using JFreeChart in SWT (I've never tried SWT myself) so this is useful...
David Gilbert
JFreeChart Project Leader

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

Murali

Works in Linux!

Post by Murali » Fri Oct 03, 2003 4:13 am

I have attempted the above method in linux under Eclipse 2.1.1. Got the chart, everything working!

Shilpa

Wow Thanx

Post by Shilpa » Fri Oct 17, 2003 8:46 pm

Hi Thanx its v good..

Jon

Post by Jon » Mon Nov 24, 2003 11:14 am

When I upgraded to ver 3 of eclipse to try and get JFreeChart to work inside swt it no longer recognised

Panel chartPanel = SWT_AWT.new_Panel(chartComposite);

From random reading on web i found:

Panel org.eclipse.swt.internal.awt.win32.SWT_AWT.new_Panel(Composite)

The new_Panel method has one parameter, an SWT Composite object, and
it returns an AWT Panel object. The awt Panel is contained within the
swt Composite, and is constructed using a WEmbeddedFrame from Sun's
internal package sun.awt.windows. Sun has changed this internal code
in jdk 1.4, and so this undocumented Eclipse mechanism does not work
with that version.

Any on e have any suggestions on how I can get graphs to display inside my SWT application?

Cheers

Jon

Robert Gash

Post by Robert Gash » Fri Apr 02, 2004 3:47 am

Jon wrote: swt Composite, and is constructed using a WEmbeddedFrame from Sun's
internal package sun.awt.windows. Sun has changed this internal code
in jdk 1.4, and so this undocumented Eclipse mechanism does not work
with that version.

Any on e have any suggestions on how I can get graphs to display inside my SWT application?
Jon,

I actually just tested a new demo using SWT 3.0M8, J2SDK 1.4.2_03, and JFreeChart 0.9.17 on my Windows XP system (SP1). I was able to use JFreeChart without any problems.

The sample code can be found at http://www.gashalot.com/software/JFreeChartSWTDemo.java.

Let me know if you have any questions.

-R

Chengdong

Dynamically dispose a chart in SWT?

Post by Chengdong » Sat May 01, 2004 5:49 pm

Hi, there:

I tried the suggestions here and found it was okay for just showing a chart in SWT application by using SWT_AWT. However there are still some potential problems exist:

SWT and AWT has diffent UI loop, they can not iteroperate seamlessly which is also discouraged by Eclipse developers.

For example, can somebody show me how to solve this problem:
==========================================
Show the pie-chart first, then click pie-chart, this will show a new bar-chart beside the pie-chart; click the bar-chart, then only show the piechart.

I tried to make this run by dynimically disposing the SWT_AWT widget, it gave me some error from SWT AWT interoperation sometime and did not work.

I think only pure SWT implementation of JFreeChart can solve this problem.

Can anybody give me some suggestion?

You can answer me by email: cli4@uky.edu

Thanks in advance.

-Chengdong

ftam_ftp

IllegalArgumentException

Post by ftam_ftp » Fri Jun 04, 2004 3:06 am

I've tried the solution above, and after working out that I should be using SWT_AWT.new_Frame(), I get an IllegalArgumentException. I've tried passing both the Composite, and the Shell as an argument, but it makes no difference. I also tried the JFreeChartSWTDemo with the same results. I'm running Eclipse 2.1.2 Build 200311030802, and using the SWT drop 3.0RC1 build 3054. Any ideas?

Thanks

Geoffrey Peart

Tried and failed

Post by Geoffrey Peart » Mon Sep 20, 2004 5:41 pm

Robert Gash wrote:
Jon wrote: swt Composite, and is constructed using a WEmbeddedFrame from Sun's
internal package sun.awt.windows. Sun has changed this internal code
in jdk 1.4, and so this undocumented Eclipse mechanism does not work
with that version.

Any on e have any suggestions on how I can get graphs to display inside my SWT application?
Jon,

I actually just tested a new demo using SWT 3.0M8, J2SDK 1.4.2_03, and JFreeChart 0.9.17 on my Windows XP system (SP1). I was able to use JFreeChart without any problems.

The sample code can be found at http://www.gashalot.com/software/JFreeChartSWTDemo.java.

Let me know if you have any questions.

-R
Robert, I attempted to run the code at that link, I am running
eclipse 3.0.0 GA with J2SDK 1.4.2_03, and I have tried jFreeChart 0.9.17 and the recent .21 releases. I enccounter two issues. the first is this:

Code: Select all

java.lang.NoClassDefFoundError: org/jfree/util/PublicCloneable
	at java.lang.ClassLoader.defineClass0(Native Method)
	at java.lang.ClassLoader.defineClass(Unknown Source)
	at java.security.SecureClassLoader.defineClass(Unknown Source)
	at java.net.URLClassLoader.defineClass(Unknown Source)
	at java.net.URLClassLoader.access$100(Unknown Source)
	at java.net.URLClassLoader$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClassInternal(Unknown Source)
	at com.gashalot.sample.JFreeChartSWTDemo.main(JFreeChartSWTDemo.java:45)
Exception in thread "main" 
That is occuring on this line :

Code: Select all

JFreeChart chart = ChartFactory.createPieChart3D("Sample Chart", pieData, true, true, false);
If I comment that, and the ones depend on it, I end up with:

Code: Select all

java.lang.IllegalArgumentException: Argument not valid
	at org.eclipse.swt.SWT.error(SWT.java:2677)
	at org.eclipse.swt.SWT.error(SWT.java:2616)
	at org.eclipse.swt.SWT.error(SWT.java:2587)
	at org.eclipse.swt.awt.SWT_AWT.new_Frame(SWT_AWT.java:118)
	at com.gashalot.sample.JFreeChartSWTDemo.main(JFreeChartSWTDemo.java:48)
Exception in thread "main" 
on line

Code: Select all

Frame chartFrame = SWT_AWT.new_Frame(shell);
Is there anything I am missing here?

If you check this, I could use your help, or anyones.

Thanks in advance.

Geoffrey Peart

In reply to my own message

Post by Geoffrey Peart » Mon Sep 20, 2004 6:50 pm

Okay first error because I am a fool :) I didn't include the jcommon.jar in my class path. The second one, well here is the javadoc for SWT_AWT class

Code: Select all

Creates a new java.awt.Frame. This frame is the root for the AWT components that will be embedded within the composite. In order for the embedding to succeed, the composite must have been created with the SWT.EMBEDDED style. 
so I changed the new shell(display) to this

Code: Select all

Shell shell = new Shell(display,SWT.EMBEDDED);
worked like a charm, not sure if that is a new release of SWT going on there or what, but it works so I'm happy. Thanks Robert for the good sample.

g

Tim99

Post by Tim99 » Tue Oct 05, 2004 6:34 pm

Unfortunately I can't use this method on Mac OS X because of this bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=67384

Mixing up AWT and SWT with Eclipse (Mac OS X) doesn't seem to work. :-(

Any suggestions?

Giuseppe

jfreechar and swt

Post by Giuseppe » Wed Oct 27, 2004 12:34 pm

Hi
I'm an italian designer and I don't speak english very well, sorry.
I have seen your message but I'm not able to put into practice your solution because eclipse tell me that the method SWT_AWT.new_Composite not exists. How can I do?

Thanks in advance,
Giuseppe

pixeldude

SWT Problem

Post by pixeldude » Mon Dec 13, 2004 2:03 pm

1. you have to create a display and a shell

Code: Select all

Display display = new Display();
Shell shell = new Shell(display);
2. Create an SWT composite with the style SWT.EMBEDDED

Code: Select all

Composite chartComposite = new Composite(shell, SWT.EMBEDDED);
3. Create an AWT Frame using SWT_AWT

Code: Select all

Frame chartFrame = SWT_AWT.new_Frame(chartComposite);
4. Go on with JFreeChart

This worked for me with SWT 3.0

Guest

Post by Guest » Fri Jan 07, 2005 5:38 pm

Tim99 wrote:Unfortunately I can't use this method on Mac OS X because of this bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=67384

Mixing up AWT and SWT with Eclipse (Mac OS X) doesn't seem to work. :-(

Any suggestions?
I had the same problem with Linux, too. But there is a way. You can save the image in a local buffer using AWT and load it from that buffer using SWT afterwards.

This is a little bit ugly, but it works...

Here is my code:

Code: Select all

  public static Image createChartImage(Control parent, JFreeChart chart,
    int width, int height)
  {
    // Color adjustment
    Color swtBackground = parent.getBackground();
    java.awt.Color awtBackground = new java.awt.Color(swtBackground.getRed(),
                                                      swtBackground.getGreen(),
                                                      swtBackground.getBlue());
    chart.setBackgroundPaint(awtBackground);
    
    try {
      // Write the image to a buffer in memory using AWT
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      ChartUtilities.writeChartAsPNG(out, chart, width, height);
      out.close();
      
      // Load the image from the same buffer using SWT
      ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
      Image swtImage = new Image(display, in);
      in.close();
      
      return swtImage;
    }
    catch (Exception exc) {
      exc.printStackTrace();
      return null;
    }
  }

Til
Posts: 1
Joined: Wed Jan 12, 2005 2:57 pm
Contact:

Post by Til » Wed Jan 12, 2005 3:16 pm

I'm the "Guest" who wrote the last post...

I just found a faster way without the indirection over creating PNG data.

Here is the code:

Code: Select all

  public static Image createChartImage(Control parent, JFreeChart chart,
    int width, int height)
  {
    // Color adjustment 
    Color swtBackground = parent.getBackground();
    java.awt.Color awtBackground = new java.awt.Color(swtBackground.getRed(),
                                                      swtBackground.getGreen(),
                                                      swtBackground.getBlue());
    chart.setBackgroundPaint(awtBackground);

    // Draw the chart in an AWT buffered image
    BufferedImage bufferedImage
      = chart.createBufferedImage(width, height, null);

    // Get the data buffer of the image
    DataBuffer buffer = bufferedImage.getRaster().getDataBuffer();
    DataBufferInt intBuffer = (DataBufferInt) buffer;
    
    // Copy the data from the AWT buffer to a SWT buffer
    PaletteData paletteData = new PaletteData(0x00FF0000, 0x0000FF00, 0x000000FF);
    ImageData imageData = new ImageData(width, height, 32, paletteData);
    for (int bank = 0; bank < intBuffer.getNumBanks(); bank++) {
      int[] bankData = intBuffer.getData(bank);
      imageData.setPixels(0, bank, bankData.length, bankData, 0);      
    }
    
    // Create an SWT image
    return new Image(parent.getDisplay(), imageData);
}

Locked