具有单个数据点的XYDataset:未绘制任何内容

时间:2014-08-31 15:11:42

标签: jfreechart

这是我遇到的一个极端案例。以下是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 方法中指示的行,则不会绘制任何内容:

enter image description here

所以问题是:我怎样才能确保在XYDataset只包含一个数据点的角落情况下至少打印一个点(或其他某个标记)?

1 个答案:

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

(注意,显然有一些关于所涉及给定对象的类型的假设 - 有疑问,在进行强制转换之前检查类型!)

结果将是仅包含单个元素的时间序列的单个刻度标记:

ChartTick

这是另一个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;
    }