这是来自this question的后续问题。
以下是:
当我启动图形并且我拖动图形时,会发生一些奇怪的事情:在某个时间间隔内,似乎每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的sourceforge页面上报告的错误问题。
可以跟踪此错误here。
答案 0 :(得分:2)
我能够重现所描述的效果。作为before,效果仅在SegmentedTimeline
时出现; DefaultTimeline
并不明显。它似乎与拖延在星期一至星期五 - 时间线的“隐藏”周末共同进行,但我没有看到明显的错误。
一种解决方法可能是让用户使用相邻控件选择TimeLine
,如example中所述。由于DefaultTimeline
为private
,因此您需要在控件的处理程序中调用getTimeline()
之前保存setTimeline()
的结果。
附录:以下是使用JCheckBox
切换Timeline
的程序的变体。单击复选框以启用SegmentedTimeline
;水平平移以查看效果(按住Control键并单击Windows;在Mac上按住Option键单击)。
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);
}
});
}
}