当前位置: 首页 > 知识库问答 >
问题:

jfreechart在使用Yahoo Finance Quotes时崩溃

徐佐
2023-03-14

我有一个非常奇怪的问题。

我所设置的是一个文件,它向雅虎财经网站发送一个url请求,然后使用结果在JFrame中绘制一个JFreeChart。

我就是不明白以下几点:

对于某些url请求,JFrame崩溃

它会启动,但只显示一个白色屏幕。而对于其他请求,我的程序运行良好。

例如:

本请求:

"http://ichart.yahoo.com/table.csv?s=GOOG&a=0&b=1&c=2011&d=6&e=24&f=2013&g=d&ignore=.csv";

很好。

但是这个要求:

"http://ichart.yahoo.com/table.csv?s=GOOG&a=2&b=1&c=2012&d=6&e=24&f=2013&g=d&ignore=.csv";

导致错误。

这怎么可能?

我知道以下几点:

  • JFrame崩溃,但JVM没有注意到它(没有注意到它崩溃)
  • 下载股票报价(JFreeChart使用的信息)在这两种情况下都很完美
  • 下载数据并显示在JFreeChart中的代码来自这个网站(RoyW发布的代码10, 2008 7:52)。
  • 进来的数据量似乎不是问题,因为在请求1中,数据点比请求2中更多
  • 我下载数据的方式并不重要(我尝试直接从url读取,我尝试将. csv文件保存到文件夹,然后从文件夹读取)
  • 这个问题不是随机出现的:我已经多次尝试启动JFrame(重新编译代码,然后运行它),但是每次错误的引用都会使JFrame崩溃。

可能与此有关的内容:

  • 当我用正确的引号启动图表并拖动图表时,奇怪的事情发生了。每隔一段时间,似乎每个周末,烛台都会变得越来越小,直到它们变成一条条纹。然后,当我拖过周末的时候,它们又变厚了,直到它们恢复正常大小。这似乎每个周末都会发生。请参阅以下图片:

所以这让我想到这可能与交易日有关。但是这也没有任何意义,因为1/1/2011(请求1)落在星期六,3/1/2012(请求2)落在星期四,而请求1成功,请求2失败。

我完全不知道该做什么。

非常感谢大家的帮助。

根据要求,这里是带有垃圾神建议的SSCCE(使用JFreechart lib v1.0.14)。

    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.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 CandlestickDemo2 extends JFrame {
        public CandlestickDemo2(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);

            //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, false);
            chartPanel.setPreferredSize(new Dimension(600, 300));

            this.add(chartPanel);
            this.pack();
        }
        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 {
                String strUrl= "http://ichart.finance.yahoo.com/table.csv?s=GOOG&a=2&b=1&c=2012&d=6&e=24&f=2013&g=d&ignore=.csv";
                URL url = new URL(strUrl);
                BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
                DateFormat df = new SimpleDateFormat("y-M-d");

                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()]);

            return data;
        }

        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new CandlestickDemo2("GOOG").setVisible(true);
                }
            });
        }
    }

这将生成一个只显示白色屏幕的JFrame。尝试将strUrl更改为

 "http://ichart.finance.yahoo.com/table.csv?s=GOOG&a=0&b=1&c=2011&d=6&e=24&f=2013&g=d&ignore=.csv";

你会注意到它工作得很好。

解决了!问题是JFreeChart版本。从v1开始更改。0.14至v1。0.15解决了所有问题。感谢垃圾神(在不知不觉中)通过广泛回答和提及所使用的库版本来解决了我的问题。

有人知道我如何帮助其他有同样问题的人吗?有没有一个我可以记录这个bug的门户?

共有1个答案

陈哲
2023-03-14

CandlestickDemo适用于jfreechart v1.0.15和任何查询。我做了两个改动:

>

  • 在事件分派线程上构造GUI;如果不这样做,将导致具有非确定性结果的数据竞争:

    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            new CandlestickDemo("GOOG").setVisible(true);
        }
    });
    

    省略备份缓冲区,尽管它可能无关紧要:

    ChartPanel chartPanel = new ChartPanel(chart, false);
    

    附录:作为参考,它看起来像是对ParamChecks的调用。在r2692中应用了NullNotAllowed(),替换了显式检查,但渲染器在其他方面没有改变。

    增编:第1节。0.14,该示例可以正确使用DateAxisDefaultTimeline,该时间线在此期间发生了重大变化。

    附录:@David Gilbert指出,相关的变化可以在r2465中找到。

  •  类似资料:
    • 我使用getStringArrayListExtra()搜索将列表从一个活动传输到另一个活动。这在第一次(从MainActivity到Diag2Activity)时运行良好,但在第二次(从Diag2Activity到SSToActivity)时应用程序崩溃。 每次我使用相同的方法:第一次活动: 第二项活动: 谁能告诉我错误可能来自哪里?提前谢谢 请在下面找到完整的代码: 主要活动。JAVA } 主

    • 问题内容: 我想每5分钟检查一次服务中的实际时间,然后根据时间将手机静音或取消静音。早些时候,我尝试在线程.sleep(300000)的末尾使用while(true),但是它总是与ANR一起崩溃,所以我尝试使用计时器任务,但是现在它在带有NullPointerException 的行之后崩溃 LogCat: 问题答案: 您需要在onCreate内初始化audioManager。

    • 当我尝试使用基于本教程的MapFragment时,并且我使用以下布局:

    • 问题内容: POI方法引发了一个我无法解决的异常: 这个错误 在我的代码中,将数据放入列后将调用该方法: 有人对此有任何帮助的线索吗? 提前致谢。 问题答案: 您已标记此android。在android上,大多数(所有?)AWT类都不可用。但是POI需要a 来计算列大小。 作为一种变通方法,代替您的来电通过。可以通过将该列中显示的最大字符数乘以一个因子来计算的近似值。首先尝试为比例字体设置大约的值

    • 这将返回一个图表对象。我如何将它与我的JavaFx节点(如HBox等)集成?

    • 问题内容: 我运行此代码,并在50分钟后收到以下错误: 当间隔时间较短时(例如 2000000 ),一切正常。 这是Node.js中的错误吗? 更新: 操作系统:,Node.js版本: 当我只运行上面的代码时,它可以正常工作,但是当它在我的应用程序中时,它确实会中断,我无法指出代码的哪一部分会中断它,因为它很长,而且看起来没有“可疑”。无论如何,当间隔更短时,它就像我写的那样工作。 问题答案: 而