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

JFreechart烛台图表拖动时的怪异行为

干善
2023-03-14

这是这个问题的后续问题。

发生的情况如下:

当我启动图形并拖动图形时,奇怪的事情发生了:在一定的间隔内,似乎每7个周期,烛台就会越来越小,直到它们变成一条条纹。然后,当我进一步拖动时,它们再次变厚,直到它们再次变为正常大小。这似乎每7个周期发生一次。

这种现象的一个示例显示在以下3张图片上:

下面的代码将准确地显示我的意思。只需编译并运行它。然后按住CTRL,用鼠标在图形上单击并按住。现在尝试向右或向左拖动图形。经过一定的拖动距离后,您会注意到错误。

我的问题:如何预防/解决这一问题?

代码:

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

            mainPlot.setDomainPannable(true);
            mainPlot.setRangePannable(true);

            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.yahoo.com/table.csv?s=GOOG&a=2&b=1&c=2013&d=4&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);
                }
            });
        }
    }

这个错误现在是JFreeChart的Source ceforge页面上报告的错误问题。

可以在此处跟踪此错误。

共有1个答案

轩辕越泽
2023-03-14

我能够重现所描述的效果。如前所述,只有分段时间线才能看到效果;这在DefaultTimeline中不明显。它似乎与周一到周五时间线的“隐藏”周末的拖拽有关,但我没有看到明显的bug。

一种解决方法可能是让用户使用相邻控件选择时间线,如本例所示。因为DefaultTimelineprivate,所以在控件的处理程序中调用setTimeline()之前,需要保存getTimeline()的结果。

附录:这里是程序的一个变体,它使用JCheckBox切换时间线。单击复选框以启用分段时间线;水平平移以查看效果(控件单击Windows;选项单击Mac)。

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.awt.event.ActionEvent;
import java.io.*;
import java.net.URL;
import java.text.*;
import java.util.*;
import java.util.List;

/**
 * @see https://stackoverflow.com/a/18421887/230513
 * @see http://www.jfree.org/forum/viewtopic.php?f=10&t=24521
 */
public class CandlestickDemo2 extends JFrame {

    public CandlestickDemo2(String stockSymbol) {
        super("CandlestickDemo2");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final 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);
        //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));
        mainPlot.setDomainPannable(true);
        mainPlot.setRangePannable(true);
        this.add(chartPanel);
        // Add tiemline toggle
        final Timeline oldTimeline = domainAxis.getTimeline();
        final Timeline newTimeline = SegmentedTimeline.newMondayThroughFridayTimeline();
        this.add(new JCheckBox(new AbstractAction("Segmented Timeline") {
            @Override
            public void actionPerformed(ActionEvent e) {
                JCheckBox jcb = (JCheckBox) e.getSource();
                if (jcb.isSelected()) {
                    domainAxis.setTimeline(newTimeline);
                } else {
                    domainAxis.setTimeline(oldTimeline);
                }
            }
        }), BorderLayout.SOUTH);
        this.pack();
        this.setLocationRelativeTo(null);
    }

    private AbstractXYDataset getDataSet(String stockSymbol) {
        //This is the dataset we are going to create
        DefaultOHLCDataset result;
        //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.yahoo.com/table.csv?s=" + stockSymbol
                + "&a=4&b=1&c=2013&d=6&e=1&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(System.err);
        }
        //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("AAPL").setVisible(true);
            }
        });
    }
}
 类似资料:
  • 这参考了蜡烛图的JFreeChart渲染。下面是使用JFreeChart生成蜡烛棒图表的代码片段。 这段代码已经过测试,并且已经运行了很长时间。但是,JFreeChart的版本已从1.0.17更改为1.0.19,使用1.0.19生成的烛台图表显示蜡烛对象/线的污迹。当我将库更改回1.0.17时,烛台对象/线再次变得清晰。 下面提供了两个库的图像。 我曾试图找出原因,但至今仍不成功。现在的问题是,由

  • 我正在开发一个显示每日财务数据的应用程序,并选择使用JFreeChart。我能够学习如何创建烛台图表,但我的问题在于定制。 你看,我的目标更像是 然而,到目前为止,我所能做的就是 无论我放大多远,烛台的宽度都不会增加。 我相当肯定,不知何故,薄烛台与一定的时间范围有关。。我已经试着去补救,但我不确定我到底做错了什么。

  • 我需要良好的阴阳烛图表为我的网络应用程序和图表http://bitcoinwisdom.com/真的是我在寻找。我喜欢你可以放大和移动的方式。有没有可能弄清楚他们在使用什么,或者你认为他们是自己编的?如果是的话用什么工具?另一个惊人的图表可以在这里找到https://www.tradingview.com/e/这两个网站比一些桌面应用程序有更好的图表,我想知道他们是如何做到的。

  • 大多数财务图表库使用一些规则来为蜡烛着色: 如果<代码>关闭 jFreeChart似乎有自己的着色规则,可以更改它们。默认情况下,该图表如下所示(某些颜色已更改): 如您所见,可以更改蜡烛、背景、绘图边框等的颜色。 我想在图表中实现规则1和2(上面)。可能吗? 结果应该是这样的: 这是我目前在示例中使用的烛台: 似乎只需将设置为并绘制颜色不变即可。 但主要问题仍然存在: > 在jFreeChart

  • 我使用OHLCSeries生成了一个JFreeChart CandlestickChart。我扩展了CandlestickRenader。在CandlestickRenader中,我覆盖了“public Paint getItemPaint(int系列,int项目)”,在其中我需要每个Stoke的日期信息来做某事,但我不知道如何获取它,请帮我解决。 部分代码如下:

  • 我试图在JFreeChart中生成一个图表,它由叠加的烛台图和Timeseries图组成。(有点像这样) 我曾尝试创建烛台图表,然后添加额外的XY系列和it渲染器,但这导致运行时错误 我的代码片段如下 如有任何意见,将不胜感激