这是我遇到的一个极端案例。以下是SSCCE:
import java.util.*;
import java.io.*;
import java.awt.Color;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.*;
import org.jfree.data.time.*;
import org.jfree.data.xy.XYDataset;
public class FooMain {
public static void main(String args[]) throws Exception {
BufferedImage img = timeAxisSSEProcessionsChart();
ImageIO.write(img, "png", new File("img.png"));
System.exit(0);
}
private static XYDataset createTimeSeriesDataset() {
TimeSeries timeSeries = new TimeSeries("series-a");
timeSeries.add(RegularTimePeriod.createInstance(Millisecond.class, new java.util.Date(0) , TimeZone.getTimeZone("Zulu")), 100);
// if below line is commented out, nothing is plotted:
timeSeries.add(RegularTimePeriod.createInstance(Millisecond.class, new java.util.Date(1000), TimeZone.getTimeZone("Zulu")), 100);
TimeSeriesCollection rv = new TimeSeriesCollection();
rv.addSeries(timeSeries);
return rv;
}
public static BufferedImage timeAxisSSEProcessionsChart() throws Exception {
XYDataset dataset = createTimeSeriesDataset();
JFreeChart chart = ChartFactory.createTimeSeriesChart("title", "date", "series-a", dataset, true, true, false);
InputStream in = new ByteArrayInputStream(imageBytesFromChart(chart, 600, 400));
return ImageIO.read(in);
}
private static byte[] imageBytesFromChart(JFreeChart chart, int width, int height) {
BufferedImage objBufferedImage = chart.createBufferedImage(width, height);
ByteArrayOutputStream bas = new ByteArrayOutputStream();
try {
ImageIO.write(objBufferedImage, "png", bas);
} catch (IOException e) {
e.printStackTrace();
}
byte[] byteArray=bas.toByteArray();
return byteArray;
}
}
上面的代码按预期产生了一个图。
如果但是我们注释掉 createTimeSeriesDataset 方法中指示的行,则不会绘制任何内容:
所以问题是:我怎样才能确保在XYDataset
只包含一个数据点的角落情况下至少打印一个点(或其他某个标记)?
答案 0 :(得分:1)
时间序列图主要由连接各个数据点的行组成。当只有一个数据元素时,没有要连接的数据点。到目前为止,这是显而易见的。
一个可能的解决方案是在只有一个条目时启用图表的“刻度形状”。我不确定这是否适合您的情况。但这可以通过像
这样的方法来完成private static void showTickMarksForSingleElements(
XYDataset dataset, JFreeChart chart)
{
TimeSeriesCollection timeSeriesCollection =
(TimeSeriesCollection)dataset;
List<?> series = timeSeriesCollection.getSeries();
TimeSeries timeSeries = (TimeSeries) series.get(0);
if (timeSeries.getItemCount() == 1)
{
XYPlot plot = (XYPlot) chart.getPlot();
XYLineAndShapeRenderer renderer
= (XYLineAndShapeRenderer) plot.getRenderer();
renderer.setSeriesShapesVisible(0, true);
}
}
(注意,显然有一些关于所涉及给定对象的类型的假设 - 有疑问,在进行强制转换之前检查类型!)
结果将是仅包含单个元素的时间序列的单个刻度标记:
这是另一个MVCE:
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.TimeZone;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
public class SingleElementChart {
public static void main(String args[]) throws Exception {
BufferedImage img = timeAxisSSEProcessionsChart();
show(img);
}
private static void show(final BufferedImage img)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new JLabel(new ImageIcon(img)));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
private static TimeSeriesCollection createTimeSeriesDataset() {
TimeSeries timeSeries = new TimeSeries("series-a");
timeSeries.add(RegularTimePeriod.createInstance(
Millisecond.class, new java.util.Date(0),
TimeZone.getTimeZone("Zulu")), 100);
// if below line is commented out, nothing is plotted:
//timeSeries.add(RegularTimePeriod.createInstance(
// Millisecond.class, new java.util.Date(1000),
// TimeZone.getTimeZone("Zulu")), 100);
TimeSeriesCollection rv = new TimeSeriesCollection();
rv.addSeries(timeSeries);
return rv;
}
public static BufferedImage timeAxisSSEProcessionsChart() throws Exception {
XYDataset dataset = createTimeSeriesDataset();
JFreeChart chart = ChartFactory.createTimeSeriesChart(
"title", "date", "series-a", dataset, true, true, false);
showTickMarksForSingleElements(dataset, chart);
InputStream in = new ByteArrayInputStream(
imageBytesFromChart(chart, 600, 400));
return ImageIO.read(in);
}
private static void showTickMarksForSingleElements(
XYDataset dataset, JFreeChart chart)
{
TimeSeriesCollection timeSeriesCollection =
(TimeSeriesCollection)dataset;
List<?> series = timeSeriesCollection.getSeries();
TimeSeries timeSeries = (TimeSeries) series.get(0);
if (timeSeries.getItemCount() == 1)
{
XYPlot plot = (XYPlot) chart.getPlot();
XYLineAndShapeRenderer renderer
= (XYLineAndShapeRenderer) plot.getRenderer();
renderer.setSeriesShapesVisible(0, true);
}
}
private static byte[] imageBytesFromChart(JFreeChart chart, int width, int height) {
BufferedImage objBufferedImage =
chart.createBufferedImage(width, height);
ByteArrayOutputStream bas = new ByteArrayOutputStream();
try {
ImageIO.write(objBufferedImage, "png", bas);
} catch (IOException e) {
e.printStackTrace();
}
byte[] byteArray=bas.toByteArray();
return byteArray;
}