Marco Montalto M.
Marco Montalto M.

Reputation: 351

JFreechart program running, but window not displayed

I am running code based on the example shown here using Eclipse on OS X, and I am using the JFreeChart and JCommon libraries.

As i said in the title, the program is running but not displaying anything. As check I have tried to print the data using the method printData() and it's working perfectly. It correctly takes the data from a yahoo csv file.

I have even tried using a small bunch of data (20 rows), but it keeps not showing.

The problem may be just in displaying the JFrame window.

The code I have inserted trying to fix it is between //BEGIN and //END comments.

Waiting for a reply,

Thank you.

SEMI-SOLVED: The code is fine, the problem is related to the JFreeChart Library.

I tried to "Build Path> Add my JFreeChart lib" in another previously working JFrame class.

When i insert the JFreeChart library, it inhibits the window display. Even if i don't import anything; just by adding the library to the building path.

As default system library i'm using "JRE System Library [JavaSE-1.7]".

Code:

package marketAnalyzer;
import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.CandlestickRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.MovingAverage;
import org.jfree.data.xy.*;

import javax.swing.*;

import java.awt.*;
import java.io.*;
import java.net.URL;
import java.text.*;
import java.util.*;
import java.util.List;



public class CandlestickDemo extends JFrame {


    public CandlestickDemo(String stockSymbol) {
        super("CandlestickDemo");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        DateAxis    domainAxis       = new DateAxis("Date");
        NumberAxis  rangeAxis        = new NumberAxis("Price");
        CandlestickRenderer renderer = new CandlestickRenderer();
        XYDataset   dataset          = getDataSet(stockSymbol);

        XYPlot mainPlot = new XYPlot(dataset, domainAxis, rangeAxis, renderer);

        final long ONE_DAY = 24 * 60 * 60 * 1000;
        XYLineAndShapeRenderer maRenderer = new XYLineAndShapeRenderer(true, false);
        XYDataset              maSataset  = MovingAverage.createMovingAverage(dataset, "MA", 30 * ONE_DAY, 0);
        mainPlot.setRenderer(1, maRenderer);
        mainPlot.setDataset (1, maSataset);

        //Do some setting up, see the API Doc
        renderer.setSeriesPaint(0, Color.BLACK);
        renderer.setDrawVolume(false);
        rangeAxis.setAutoRangeIncludesZero(false);
        domainAxis.setTimeline( SegmentedTimeline.newMondayThroughFridayTimeline() );

        //Now create the chart and chart panel
        JFreeChart chart = new JFreeChart(stockSymbol, null, mainPlot, false);
        ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new Dimension(600, 300));

        this.add(chartPanel);
        this.pack();

        //BEGIN

        //TRYING TO DISPLAY THE WINDOW

        chartPanel.setLayout(new java.awt.BorderLayout());
        chartPanel.validate();
        this.setLayout(new java.awt.BorderLayout());
        this.validate();
        chartPanel.repaint();
        this.repaint();


        //END
    }
    protected AbstractXYDataset getDataSet(String stockSymbol) {
        //This is the dataset we are going to create
        DefaultOHLCDataset result = null;
        //This is the data needed for the dataset
        OHLCDataItem[] data;

        //This is where we go get the data, replace with your own data source
        data = getData(stockSymbol);

        //Create a dataset, an Open, High, Low, Close dataset
        result = new DefaultOHLCDataset(stockSymbol, data);

        return result;
    }
    //This method uses yahoo finance to get the OHLC data
    protected OHLCDataItem[] getData(String stockSymbol) {
        List<OHLCDataItem> dataItems = new ArrayList<OHLCDataItem>();
        try {
            //INTERNET DATA
            //              String strUrl= "http://ichart.finance.yahoo.com/table.csv?s="+stockSymbol+"&a=0&b=1&c=2008&d=3&e=30&f=2008&ignore=.csv";
            //              URL url = new URL(strUrl);
            //              BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
            //              DateFormat df = new SimpleDateFormat("y-M-d");


            //BEGIN
            FileReader r;
            BufferedReader in;

            r = new FileReader("nasdaqSmall.csv");

            in = new BufferedReader(r);
            DateFormat df = new SimpleDateFormat("y-M-d");

            //END


            String inputLine;
            in.readLine();
            while ((inputLine = in.readLine()) != null) {
                StringTokenizer st = new StringTokenizer(inputLine, ",");

                Date date       = df.parse( st.nextToken() );
                double open     = Double.parseDouble( st.nextToken() );
                double high     = Double.parseDouble( st.nextToken() );
                double low      = Double.parseDouble( st.nextToken() );
                double close    = Double.parseDouble( st.nextToken() );
                double volume   = Double.parseDouble( st.nextToken() );
                double adjClose = Double.parseDouble( st.nextToken() );

                OHLCDataItem item = new OHLCDataItem(date, open, high, low, close, volume);
                dataItems.add(item);
            }
            in.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        //Data from Yahoo is from newest to oldest. Reverse so it is oldest to newest
        Collections.reverse(dataItems);

        //Convert the list into an array
        OHLCDataItem[] data = dataItems.toArray(new OHLCDataItem[dataItems.size()]);



        //BEGIN
        //DEBUG
        printData(data);
        //END

        return data;
    }

    public static void main(String[] args) {
        new CandlestickDemo("MSFT").setVisible(true);

    }

    //PRINT DATA
    public static void printData(OHLCDataItem[] data){
        for(OHLCDataItem el: data){
            System.out.println(""+el.getDate()+" "+el.getOpen()+" "+el.getHigh()+" "+el.getLow()+" "+el.getClose()+
                    " "+el.getVolume());

        }
    }


}

Upvotes: 3

Views: 2008

Answers (3)

Liron
Liron

Reputation: 46

I was having this issue as well. It comes from adding all of the jars in the JFreeChart lib to the build path. By removing the unnecessary and adding only the jfreechart-1.0.19 and jcommon-1.0.23 jars, my applications started running with the window and chart displayed.

Upvotes: 3

CN1002
CN1002

Reputation: 1115

Try this:

Your class should extends the ApplicationFrame from the import org.jfree.ui. package. Now instead of using frame.getContentPane() use setContentPane(myChartPanel).

Your code Should then look like:

final JFreeChart myChart = createChart(dataset);
    final ChartPanel myChartPanel = new ChartPanel(myChart);
    myChartPanel.setPreferredSize(new java.awt.Dimension(500, 500));
    setContentPane(myChartPanel);

Upvotes: 0

andyroberts
andyroberts

Reputation: 3518

I can't see how all the validate/repaints are going to help. As a general rule if you are going to change a container's layout manager, do it first and then add components to it.

JFrame's contain a JRootPane and this has a contentPane. Technically it's this contentPane which you need to add components too. You get to this using the frame's getContentPane() method. But that did become cumbersome so JFrame was made a little easier to use. From the docs:

As a conveniance add and its variants, remove and setLayout have been overridden to forward to the contentPane as necessary. This means you can write:

   frame.add(child);   

And the child will be added to the contentPane.

But I can't remember when that convenience was added - possibly Java6 so be sure you're using at least jdk1.6.

The other thing to note is the contentPane's default layout:

The default content pane will have a BorderLayout manager set on it.

So no need to set your frame to use the BorderLayout either. When using BorderLayout you ought to provide the location when adding a component, e.g. BorderLayout.CENTER. As it happens I don't think that's the cause of your bug as I think by default it assumes CENTER. But still, it's good practise.

I must admit that I always use the more verbose version and interact directly via getContentPane() for add() and setLayout() on JFrames rather than the convenience methods mainly from habit but it does make it clear what I am actually doing. I'd recommend you do the same for now.

I've created a smaller, simpler version of an app displaying a chart for you to work from.

import javax.swing.*;
import java.awt.*;
import org.jfree.chart.*;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

class Test {

    private JFrame frame;

    public Test() {

        frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel aPanel = new JPanel();
        aPanel.setPreferredSize(new Dimension(600, 300));


        ChartPanel chartPanel = new ChartPanel(createChart());
        chartPanel.setPreferredSize(new Dimension(600, 300));

        frame.getContentPane().add(chartPanel);

        frame.pack();
        frame.setVisible(true);
    }

    private JFreeChart createChart() {

        TimeSeries series = new TimeSeries("time series", Day.class);
        series.add(new Day(1,1,2014), 100 );  
        series.add(new Day(1,2,2014), 150);  
        series.add(new Day(1,3,2014), 70 );  
        series.add(new Day(1,4,2014), 210 );  
        series.add(new Day(1,5,2014), 310);
        series.add(new Day(1,6,2014), 260 );  
        TimeSeriesCollection dataset = new TimeSeriesCollection();  
        dataset.addSeries(series);  
        JFreeChart timechart = ChartFactory.createTimeSeriesChart(  
                "Vistors Count Chart", // Title  
                "Date",         // X-axis Label 
                "Visitors",       // Y-axis Label  
                dataset,        // Dataset  
                true,          // Show legend  
                true,          // Use tooltips  
                false          // Generate URLs  
        );

        return timechart;

    }

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

}

This works using java/javac 1.7; jcommon-1.0.23; jfreechart-1.0.19.

Upvotes: 0

Related Questions