JFreechart烛台图表在拖动时的奇怪行为 [英] JFreechart candlestick chart weird behaviour on drag

查看:177
本文介绍了JFreechart烛台图表在拖动时的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是来自。

解决方案

我能够重现所描述的效果。作为之前,效果只能通过 SegmentedTimeline ;使用 DefaultTimeline 并不明显。它似乎与拖拽星期一至星期五 - 时间线的隐藏周末共存,但我没有看到明显的错误。



一种解决方法可能是让用户使用相邻控件选择 TimeLine ,如示例。因为 DefaultTimeline private ,所以你需要保存 getTimeline()<的结果/ code>在控件的处理程序中调用 setTimeline()之前。



附录:这是一个变体使用 JCheckBox 来切换时间轴的程序。单击复选框以启用 SegmentedTimeline ;水平平移以查看效果(按住Control键并单击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
* /
公共类CandlestickDemo2扩展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);
//做一些设置,参见API Doc
renderer.setSeriesPaint(0,Color.BLACK);
renderer.setDrawVolume(false);
rangeAxis.setAutoRangeIncludesZero(false);
//现在创建图表和图表面板
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);
//添加tiemline toggle
final时间轴oldTimeline = domainAxis.getTimeline();
final时间轴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){
//这是我们要创建的数据集
DefaultOHLCDataset结果;
//这是数据集
OHLCDataItem []数据所需的数据;
//这是我们获取数据的地方,替换为您自己的数据源
data = getData(stockSymbol);
//创建一个数据集,一个Open,High,Low,Close数据集
result = new DefaultOHLCDataset(stockSymbol,data);
返回结果;
}
//此方法使用yahoo finance获取OHLC数据

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&安培;忽略=的.csv;
URL url =新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(例外e){
e.printStackTrace(System.err);
}
//来自雅虎的数据是从最新到最旧的。反转所以它是最旧的最新的
Collections.reverse(dataItems);
//将列表转换为数组
OHLCDataItem [] data = dataItems.toArray(new OHLCDataItem [dataItems.size()]);
返回数据;
}

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


This is a follow up question from this question.

What happens is the following:

When I launch the graph and I drag the graph around, something weird happens: at a certain interval, it seems every 7 periods, the candlesticks get smaller and smaller untill they are only a stripe. Then when I drag further, they become thicker again until they are normal size again. This seems to happen for every 7 periods.

An example of this phenomenon is displayed on to the following 3 pictures:

The following code will show exactly what I mean. Just compile and run it. Then press and hold CTRL and click and hold with your mouse on the graph. Now try dragging the graph to the right or left. After a certain 'dragging distance' you will notice the bug.

My question: How to prevent/ workaround this?

Code:

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

Update

This bug is now a reported bug issue on the sourceforge page of JFreeChart.

This bug can be tracked here.

解决方案

I am able to reproduce the effect described. As before, the effect is seen only with a SegmentedTimeline; it is not apparent with the DefaultTimeline. It appears to co-incide with dragging across the "hidden" weekends of a monday-through-friday-timeline, but I don't see an obvious bug.

One workaround might be to let the user choose the TimeLine using an adjacent control, as suggested in this example. Because DefaultTimeline is private, you'll need to save the result from getTimeline() before calling setTimeline() in the control's handler.

Addendum: Here's a variation of the program that uses a JCheckBox to toggle the Timeline. Click the check box to enable the SegmentedTimeline; pan horizontally to see the effect (control-click on Windows; option-click on 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烛台图表在拖动时的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆