Reputation: 351
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
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
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
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