JFreeChart in MacOS in a swing node - overcoming a hang

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
DullingWine
Posts: 7
Joined: Fri Jun 27, 2014 2:01 am
antibot: No, of course not.

JFreeChart in MacOS in a swing node - overcoming a hang

Post by DullingWine » Fri Jun 27, 2014 2:11 am

Hello

Is anyone successfully using JFreechart on a Mac (Mavericks) using Java 8 (1.8.0_05) - in a JavaFX SwingNode? I have submitted a java bug report for a hang in CGLGraphicsConfig.getMaxTextureSize which seems to happen for even the most trivial of Jfreecharts. I have enclosed the code below to reproduce. I'm just wondering whether anyone has come across, and found a fix/workaround? The bug itself (or something really similar) seems to have featured before but was closed a few times in jdk 7. I can't use jdk 7 though. I adapted the same chart from one of the demos, and made it really minimal.
This all works fine on a PC by the way, and apart from sizing issues have not had any problems with JfreeChart inside a SwingNode on a PC.

Thanks!

Code: Select all

package demo;

import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

import javax.swing.SwingUtilities;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class AwtBugDemonstrator extends Application {
	
	@Override
	public void start(Stage primaryStage) {
		try {		
			primaryStage.setTitle("Awt Bug Demonstrator");	
			BorderPane bp = new BorderPane();
			Scene scene = new Scene(bp, 400, 400);
			
			SwingNode sn = new SwingNode();
			ChartPanel c = new ChartSample().getPanel();
			
			try {
			SwingUtilities.invokeAndWait(
				()->{
						// hangs inside here...
						sn.setContent(c);
					}
			);
			} catch (Exception ex) {
				ex.printStackTrace();
			}
			
			bp.setCenter(sn);	
			primaryStage.setScene(scene);
			primaryStage.show();		
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		launch(args);
	}

	//public class LineChartDemo6 extends ApplicationFrame {
	public class ChartSample  {
		ChartPanel chartPanel;
	    public ChartSample() {

	        final XYDataset dataset = createDataset();
	        final JFreeChart chart = createChart(dataset);
	        chartPanel = new ChartPanel(chart);
	        chartPanel.setPreferredSize(new java.awt.Dimension(400, 400));

	    }
	    
	    public ChartPanel getPanel() {
	    	return chartPanel;
	    }
	    
	    private XYDataset createDataset() {
	        
	        final XYSeries series1 = new XYSeries("First");
	        series1.add(1.0, 1.0);
	        final XYSeriesCollection dataset = new XYSeriesCollection();
	        dataset.addSeries(series1);                
	        return dataset;
	        
	    }
	
	    private JFreeChart createChart(final XYDataset dataset) {
	        
	        final JFreeChart chart = ChartFactory.createXYLineChart(
	            "Bug Demonstrator",   "X",    "Y",   dataset,             
	            PlotOrientation.VERTICAL,true, true, false    
	        );

	        final XYPlot plot = chart.getXYPlot();
	        
	        final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
	        plot.setRenderer(renderer);
	        
	        return chart;
	        
	    }
	}

}

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

Re: JFreeChart in MacOS in a swing node - overcoming a hang

Post by david.gilbert » Fri Jun 27, 2014 5:44 am

I've not used the SwingNode so I can't help on that, hopefully someone else can. But I thought I would let you know that the next release of JFreeChart (1.0.18) will add JavaFX support with the addition of a ChartViewer JavaFX control that will render charts to a JavaFX Canvas using the FXGraphics2D implementation that I wrote for Orson Charts. The ChartViewer will support tooltips, zooming (drag and mouse-wheel), panning, the right-click menu for export to PNG/JPEG/SVG/PDF and chart mouse listeners similar to what is available in the Swing ChartPanel. The code has not yet been committed in SVN, but it is close now (most likely it will be there today).
David Gilbert
JFreeChart Project Leader

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

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

Re: JFreeChart in MacOS in a swing node - overcoming a hang

Post by david.gilbert » Fri Jun 27, 2014 11:45 am

David Gilbert
JFreeChart Project Leader

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

DullingWine
Posts: 7
Joined: Fri Jun 27, 2014 2:01 am
antibot: No, of course not.

Re: JFreeChart in MacOS in a swing node - overcoming a hang

Post by DullingWine » Fri Jun 27, 2014 12:29 pm

Briliant Dave - this is just what i've been waiting for. As I said i got my Jfreechart working under JavaFx but in order to get it to resize properly as the JavaFX container was resized, i had to add a listener to the the width/height properties of the java fx container and then set the bounds on the chart panel accordingly. I also had problems with repainting etc. Hopefully this will solve all that.

As for the mac specific bug - well i did find a workaround late last night - i had to split up the things i was doing in the invokeAndWait to do just the things i was dependent on in invokeAndWait and then the setContent in an invokeLater. This then worked. But definitely a mac only bug as far as i can see since it worked fine on a PC.

cgmollo
Posts: 2
Joined: Tue Sep 22, 2015 2:43 pm
antibot: No, of course not.

Re: JFreeChart in MacOS in a swing node - overcoming a hang

Post by cgmollo » Tue Sep 22, 2015 3:06 pm

I have been experimenting with using the JavaFX SwingNode to display a JFreeChart chart in a JavaFX app. As far as I could find, there is not much discussion on this topic on the Web. This thread was one of the best I found. Anyhow, I thought I would add to the discussion what I have discovered.

The documentation for SwingNode states:
The hierarchy of components contained in the JComponent instance should not contain any heavyweight components, otherwise SwingNode may fail to paint it.
Elsewhere I read that anything derived from java.awt.Component will generate a heavyweight component. The ChartPanel class is a descendant of java.awt.Component. So, it is probably not a recommended approach to use SwingNode to display a JFreeChart chart in a JavaFX app. Nonetheless, I tried it and it seems to work except for the chart disappears (fails to get repainted) when I resize the window (just as the SwingNode documentation predicted). I solved the repaint problem by adding listeners to the width and height properties of the window and simply calling the repaint() method on the ChartPanel object:

Code: Select all

        primaryStage.widthProperty().addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                SwingUtilities.invokeLater(() -> {
                    chartPanel.repaint();
                });
            }
        });
        
        primaryStage.heightProperty().addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                SwingUtilities.invokeLater(() -> {
                    chartPanel.repaint();
                });
            }
        });
I'm not sure if this is a good solution or not. I don't know much about Swing.

Anyhow, I also tried the ChartViewer JavaFX control that was recently added to JFreeChart. It seems to work great! Thanks Dave! Using the ChartViewer JavaFX control is probably the better approach.

Locked