JFreeChart生成股票9:30-15:00時序圖

當前JFreechart版本1.5.0

<dependency>
    <groupId>org.jfree</groupId>
    <artifactId>jfreechart</artifactId>
    <version>1.5.0</version>
</dependency>

A股交易時間爲9:30-11:30,13:00-15:00,11:31-12:59分之間是沒有數據的,X軸時間刻度也只顯示9:30、10:30、11:30、14:00、15:00這5個刻度值。
要實現這個時間顯示效果有兩種方式:
1、直接使用ChartFactory.createTimeSeriesChart()實現,由於默認下顯示的時間是連續的,11:31-12:59沒有數值,會顯示成一條直線,爲了實現數據的連續,需要把13:00-15:00換算成11:31-13:30的數值,實現代碼:

package test.jfreechar;

import com.penngo.utils.DateUtil;
import com.penngo.utils.ToolUtil;
import org.apache.commons.io.FileUtils;
import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.ui.*;
import org.jfree.data.time.*;
import org.jfree.data.xy.XYDataset;

import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileOutputStream;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.time.LocalDateTime;
import java.util.List;
import java.util.*;

public class Time1Data extends ApplicationFrame {

    public Time1Data(String title) {
        super(title);
        XYDataset xydataset = createDataSet();
        JFreeChart jfreechart = createChart(xydataset);
        ChartPanel chartpanel = new ChartPanel(jfreechart);
        chartpanel.setPreferredSize(new Dimension(865, 250));
        setContentPane(chartpanel);
    }

    public List<List<String>> getJsonData(){
        List<List<String>> list = new ArrayList<>();
        try{
            String content = FileUtils.readFileToString(new File("template/eastmoney/eastmoney.json"), "UTF-8");
            Map<String, Object> resultMap = ToolUtil.strToMap(content);
            Map<String, Object> data = (Map<String, Object>)resultMap.get("data");
            List<String> s2nList = (List<String>)data.get("s2n");

            for(String s2n:s2nList) {
                String[] strs = s2n.split(",");
                String timeStr = strs[0];
                String shIn = strs[1];
                double shInFloat = shIn.equals("-") ? -10000 : Double.valueOf(shIn) / 10000;
                shInFloat = new BigDecimal(shInFloat).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

                String szIn = strs[3];
                double szInFloat = szIn.equals("-") ? -10000 : Double.valueOf(szIn) / 10000;
                szInFloat = new BigDecimal(szInFloat).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

                String totalIn = strs[5];
                double totalInFloat = totalIn.equals("-") ? -10000 : Double.valueOf(totalIn) / 10000;
                totalInFloat = new BigDecimal(totalInFloat).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                list.add(Arrays.asList(timeStr, String.valueOf(totalInFloat), String.valueOf(shInFloat), String.valueOf(szInFloat)));
            }
         }
        catch(Exception e){
            e.printStackTrace();
        }
        return list;
    }
    private String saveImage(JFreeChart jfreechart){
        String imgBase64 = null;
        FileOutputStream fos_jpg=null;
        try {
            File img = new File("template/eastmoney/char_time1.png");
            fos_jpg = new FileOutputStream(img,false);
            // 將報表保存爲png文件
            ChartUtils.writeChartAsPNG(fos_jpg, jfreechart, 865, 250);
            fos_jpg.close();
            imgBase64 = ToolUtil.img2base64(img);
        } catch (Exception e) {
            e.printStackTrace();

        } finally {
            try {
                fos_jpg.close();
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
        return imgBase64;
    }

    private XYDataset createDataSet(){
        TimeSeries timeseries1 = new TimeSeries("指數1");
        TimeSeries timeseries2 = new TimeSeries("指數2");
        TimeSeries timeseries3 = new TimeSeries("指數3");

        List<List<String>> list = getJsonData();
        for(List<String> strs:list){
            String timeStr = strs.get(0);
            String dateStr = DateUtil.dateToStr(new Date(), "yyyy-MM-dd "+timeStr+":ss");
            LocalDateTime localDateTime = DateUtil.strToLocalDateTime(dateStr, "yyyy-MM-dd H:mm:ss");

            Number totalInFloat = strs.get(1).equals("-10000.0") ? (Number)null : Double.valueOf(strs.get(1));
            Number hk2shFloat = strs.get(2).equals("-10000.0") ? (Number)null : Double.valueOf(strs.get(2));
            Number hk2sFloat = strs.get(3).equals("-10000.0") ? (Number)null : Double.valueOf(strs.get(3));
            Day day = new Day();
            int hour = localDateTime.getHour();
            int minute = localDateTime.getMinute();
            if(hour > 12){
                localDateTime = localDateTime.plusMinutes(-90);
                hour = localDateTime.getHour();
                minute = localDateTime.getMinute();
            }

            timeseries1.add(new Minute(minute, new Hour(hour, day)), totalInFloat);
            timeseries2.add(new Minute(minute, new Hour(hour, day)), hk2shFloat);
            timeseries3.add(new Minute(minute, new Hour(hour, day)), hk2sFloat);
        }
        TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();
        timeseriescollection.addSeries(timeseries1);
        timeseriescollection.addSeries(timeseries2);
        timeseriescollection.addSeries(timeseries3);

        return timeseriescollection;
    }

    private static JFreeChart createChart(XYDataset xydataset)
    {
        StandardChartTheme standardChartTheme = new StandardChartTheme("JFree"); //或者爲Legacy
        standardChartTheme.setRegularFont(new Font("宋體", Font.BOLD, 12));
        standardChartTheme.setExtraLargeFont(new Font("宋體", Font.BOLD, 12));
        standardChartTheme.setSmallFont(new Font("宋體", Font.BOLD, 12));
        standardChartTheme.setLargeFont(new Font("宋體", Font.BOLD, 12));
        ChartFactory.setChartTheme(standardChartTheme);
        JFreeChart jfreechart = ChartFactory.createTimeSeriesChart("股市指數測試", "", "", xydataset, false, true, false);

        TextTitle subtitle1 = new TextTitle("日期:" + DateUtil.getNowStr("yyyy年MM月dd日     "));
        subtitle1.setPaint(new Color(144,144,144));
        subtitle1.setPosition(RectangleEdge.TOP);
        subtitle1.setHorizontalAlignment(HorizontalAlignment.RIGHT);
        jfreechart.addSubtitle(subtitle1);

        TextTitle subtitle2 = new TextTitle("注:資金數據僅供參考\n來自:https://my.oschina.net/penngo製圖");
        subtitle2.setPaint(new Color(144,144,144));
        subtitle2.setPosition(RectangleEdge.BOTTOM);
        subtitle2.setHorizontalAlignment(HorizontalAlignment.CENTER);
        subtitle2.setMargin(4.0D, 0.0D, 2.0D, 4.0D);
        jfreechart.addSubtitle(subtitle2);

        jfreechart.setBorderVisible(false);
        XYPlot plot = (XYPlot) jfreechart.getPlot();
        plot.setBackgroundPaint(Color.WHITE);
        plot.setDomainGridlinePaint(Color.lightGray);
        plot.setRangeGridlinePaint(Color.lightGray);
        plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 20.0));
        plot.setDomainCrosshairVisible(true);
        plot.setRangeCrosshairVisible(true);

        LegendItemCollection var5 = new LegendItemCollection();
        var5.add(new LegendItem("指數1", (String)null, (String)null, (String)null, new Rectangle2D.Double(-6.0D, -3.0D, 12.0D, 12.0D), new Color(107, 57,6)));
        var5.add(new LegendItem("指數2", (String)null, (String)null, (String)null, new Rectangle2D.Double(-6.0D, -3.0D, 12.0D, 12.0D), new Color(35, 131,252)));
        var5.add(new LegendItem("指數3", (String)null, (String)null, (String)null, new Rectangle2D.Double(-6.0D, -3.0D, 12.0D, 12.0D), new Color(255, 91,255)));
        plot.setFixedLegendItems(var5);
        plot.setInsets(new RectangleInsets(5.0D, 5.0D, 5.0D, 20.0D));
        LegendTitle var6 = new LegendTitle(plot);
        var6.setPosition(RectangleEdge.BOTTOM);
        jfreechart.addSubtitle(var6);

        XYItemRenderer r = plot.getRenderer();
        if (r instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;
            renderer.setSeriesPaint(0, new Color(107, 57,6));
            renderer.setSeriesPaint(1, new Color(35, 131,252));
            renderer.setSeriesPaint(2, new Color(255, 91,255));
        }
        plot.setDomainAxis(new CustomDateAxis());

        DateAxis dateAxis = (DateAxis) plot.getDomainAxis();
        Date minDate = dateAxis.getMinimumDate();
        minDate.setHours(9);
        minDate.setMinutes(30);
        Date maxDate = dateAxis.getMaximumDate();
        maxDate.setHours(13);
        maxDate.setMinutes(30);
        System.out.println("====minDate:" + DateUtil.dateToStr(minDate, "yyyy-MM-dd HH:mm:ss") + ", maxDate:" + DateUtil.dateToStr(maxDate, "yyyy-MM-dd HH:mm:ss"));
        dateAxis.setRange(minDate, maxDate);;
        //plot.setRangeAxis(new CustomNumberAxis());
        NumberAxis valueAxis = (NumberAxis)plot.getRangeAxis();
        return jfreechart;
    }

    private static class CustomNumberAxis extends NumberAxis{
        public List refreshTicks(Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) {
            List result = new ArrayList();
            if (RectangleEdge.isTopOrBottom(edge)) {
                result = this.refreshTicksHorizontal(g2, dataArea, edge);
            } else if (RectangleEdge.isLeftOrRight(edge)) {
                result = this.refreshTicksVertical(g2, dataArea, edge);
            }
            return (List)result;
        }
    }
    private static class CustomDateAxis extends DateAxis{
        public List refreshTicks(Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) {
            List result = null;//new ArrayList();
            if (RectangleEdge.isTopOrBottom(edge)) {
                Font tickLabelFont = this.getTickLabelFont();
                g2.setFont(tickLabelFont);
                if (this.isAutoTickUnitSelection()) {
                    this.selectAutoTickUnit(g2, dataArea, edge);
                }
                DateTickUnit unit = this.getTickUnit();
                Date tickDate = this.calculateLowestVisibleTickValue(unit);
                result = new ArrayList();
                Map<String, String> dateMap = new LinkedHashMap<String, String>(){{
                    put("09:30","09:30");
                    put("10:30","10:30");
                    put("11:30","11:30");
                    put("12:30","14:00");
                    put("13:30","15:00");
                }};
                for(String timeStr:dateMap.keySet()){
                    String timeValue = dateMap.get(timeStr);
                    String time = DateUtil.dateToStr(tickDate, "yyyy-MM-dd " +timeStr+ ":ss");
                    Date date = DateUtil.strToDate(time, "yyyy-MM-dd HH:mm:ss");
                    Tick tick = new DateTick(date, timeValue, TextAnchor.TOP_CENTER, TextAnchor.TOP_CENTER, 0.0);
                    result.add(tick);
                }

            } else if (RectangleEdge.isLeftOrRight(edge)) {
                result = this.refreshTicksVertical(g2, dataArea, edge);
            }
            return result;
        }

        protected List refreshTicksHorizontal(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge) {
            List result = new ArrayList();
            Font tickLabelFont = this.getTickLabelFont();
            g2.setFont(tickLabelFont);
            if (this.isAutoTickUnitSelection()) {
                this.selectAutoTickUnit(g2, dataArea, edge);
            }

            DateTickUnit unit = this.getTickUnit();
            Date tickDate = this.calculateLowestVisibleTickValue(unit);
            Date upperDate = this.getMaximumDate();
            boolean hasRolled = false;
            while(true) {
                while(tickDate.before(upperDate)) {
                    if (!hasRolled) {
                        //tickDate = this.correctTickDateForPosition(tickDate, unit, this.getTickMarkPosition());
                    }
                    long lowestTickTime = tickDate.getTime();
                    long distance = unit.addToDate(tickDate, this.getTimeZone()).getTime() - lowestTickTime;
                    int minorTickSpaces = this.getMinorTickCount();
                    if (minorTickSpaces <= 0) {
                        minorTickSpaces = unit.getMinorTickCount();
                    }
                    for(int minorTick = 1; minorTick < minorTickSpaces; ++minorTick) {
                        long minorTickTime = lowestTickTime - distance * (long)minorTick / (long)minorTickSpaces;
                        if (minorTickTime > 0L && this.getRange().contains((double)minorTickTime) && !this.isHiddenValue(minorTickTime)) {
                            result.add(new DateTick(TickType.MINOR, new Date(minorTickTime), "", TextAnchor.TOP_CENTER, TextAnchor.CENTER, 0.0D));
                        }
                    }

                    if (!this.isHiddenValue(tickDate.getTime())) {
                        DateFormat formatter = this.getDateFormatOverride();
                        String tickLabel;
                        if (formatter != null) {
                            tickLabel = formatter.format(tickDate);
                        } else {
                            tickLabel = this.getTickUnit().dateToString(tickDate);
                        }

                        double angle = 0.0D;
                        TextAnchor anchor;
                        TextAnchor rotationAnchor;
                        if (this.isVerticalTickLabels()) {
                            anchor = TextAnchor.CENTER_RIGHT;
                            rotationAnchor = TextAnchor.CENTER_RIGHT;
                            if (edge == RectangleEdge.TOP) {
                                angle = 1.5707963267948966D;
                            } else {
                                angle = -1.5707963267948966D;
                            }
                        } else if (edge == RectangleEdge.TOP) {
                            anchor = TextAnchor.BOTTOM_CENTER;
                            rotationAnchor = TextAnchor.BOTTOM_CENTER;
                        } else {
                            anchor = TextAnchor.TOP_CENTER;
                            rotationAnchor = TextAnchor.TOP_CENTER;
                        }

                        Tick tick = new DateTick(tickDate, tickLabel, anchor, rotationAnchor, angle);
                        result.add(tick);
                        hasRolled = false;
                        long currentTickTime = tickDate.getTime();
                        tickDate = unit.addToDate(tickDate, this.getTimeZone());
                        long nextTickTime = tickDate.getTime();

                        for(int minorTick = 1; minorTick < minorTickSpaces; ++minorTick) {
                            long minorTickTime = currentTickTime + (nextTickTime - currentTickTime) * (long)minorTick / (long)minorTickSpaces;
                            if (this.getRange().contains((double)minorTickTime) && !this.isHiddenValue(minorTickTime)) {
                                result.add(new DateTick(TickType.MINOR, new Date(minorTickTime), "", TextAnchor.TOP_CENTER, TextAnchor.CENTER, 0.0D));
                            }
                        }
                    } else {
                        tickDate = unit.rollDate(tickDate, this.getTimeZone());
                        hasRolled = true;
                    }
                }

                return result;
            }
        }
    }

    public static void main(String args[])
    {
        Time1Data timeseriesdemo10 = new Time1Data("股市9:30-15:00指數時序圖");
        timeseriesdemo10.pack();
        timeseriesdemo10.setVisible(true);
    }
}

生成圖片效果:

2、直接使用自帶的折線圖,但是默認的X軸座標值不能只顯示9:30、10:30、11:30、14:00、15:00這5個刻度值,需要重寫CategoryPlot.drawDomainGridlines、CategoryAxis.refreshTicks、CategoryAxis.drawCategoryLabels三個方法,實現代碼如下:

package test.jfreechar;

import com.penngo.utils.DateUtil;
import com.penngo.utils.ToolUtil;
import org.apache.commons.io.FileUtils;
import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.entity.CategoryLabelEntity;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.text.TextBlock;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.ui.ApplicationFrame;
import org.jfree.chart.ui.HorizontalAlignment;
import org.jfree.chart.ui.RectangleEdge;
import org.jfree.chart.ui.RectangleInsets;
import org.jfree.chart.util.Args;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;

import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.math.BigDecimal;
import java.util.List;
import java.util.*;


public class Time2Data extends ApplicationFrame {

    public Time2Data(String title) {
        super(title);
        DefaultCategoryDataset xydataset = createDataSet();
        JFreeChart jfreechart = createChart(xydataset);
        ChartPanel chartpanel = new ChartPanel(jfreechart);
        chartpanel.setPreferredSize(new Dimension(862, 250));
        setContentPane(chartpanel);
    }

    public List<List<String>> getJsonData(){
        List<List<String>> list = new ArrayList<>();
        try{
            String content = FileUtils.readFileToString(new File("template/eastmoney/penngo_data.json"), "UTF-8");
            Map<String, Object> resultMap = ToolUtil.strToMap(content);
            Map<String, Object> data = (Map<String, Object>)resultMap.get("data");
            List<String> s2nList = (List<String>)data.get("s2n");

            for(String s2n:s2nList) {

                String[] strs = s2n.split(",");
                String timeStr = strs[0];
                String shIn = strs[1];
                double shInFloat = shIn.equals("-") ? -10000 : Double.valueOf(shIn) / 10000;
                shInFloat = new BigDecimal(shInFloat).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

                String szIn = strs[3];
                double szInFloat = szIn.equals("-") ? -10000 : Double.valueOf(szIn) / 10000;
                szInFloat = new BigDecimal(szInFloat).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

                String totalIn = strs[5];
                double totalInFloat = totalIn.equals("-") ? -10000 : Double.valueOf(totalIn) / 10000;
                totalInFloat = new BigDecimal(totalInFloat).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                list.add(Arrays.asList(timeStr, String.valueOf(totalInFloat), String.valueOf(shInFloat), String.valueOf(szInFloat)));
            }
         }
        catch(Exception e){
            e.printStackTrace();
        }
        return list;
    }

    private DefaultCategoryDataset createDataSet(){
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        List<List<String>> list = getJsonData();
        int count = 0;
        for(List<String> strs:list){
            String timeStr = strs.get(0);

            Number totalInFloat = strs.get(1).equals("-10000.0") ? (Number)null : Double.valueOf(strs.get(1));
            Number hk2shFloat = strs.get(2).equals("-10000.0") ? (Number)null : Double.valueOf(strs.get(2));
            Number hk2szloat = strs.get(3).equals("-10000.0") ? (Number)null : Double.valueOf(strs.get(3));

            dataset.addValue(totalInFloat, "指數1", timeStr);
            dataset.addValue(hk2shFloat, "指數2", timeStr);
            dataset.addValue(hk2szloat, "指數3", timeStr);
        }
        return dataset;
    }

    private static JFreeChart createChart(DefaultCategoryDataset xydataset)
    {
        StandardChartTheme standardChartTheme = new StandardChartTheme("JFree"); //或者爲Legacy
        standardChartTheme.setRegularFont(new Font("宋體", Font.BOLD, 12));
        standardChartTheme.setExtraLargeFont(new Font("宋體", Font.BOLD, 12));
        standardChartTheme.setSmallFont(new Font("宋體", Font.BOLD, 12));
        standardChartTheme.setLargeFont(new Font("宋體", Font.BOLD, 12));
        ChartFactory.setChartTheme(standardChartTheme);

        JFreeChart jfreechart = createLineChart(
                "股市指數測試", // chart title
                "時間", // domain axis label
                "資金", // range axis label
                xydataset, // data
                PlotOrientation.VERTICAL, // orientation
                false, // include legend
                true, // tooltips
                false // urls
        );

        TextTitle subtitle1 = new TextTitle("日期:" + DateUtil.getNowStr("yyyy年MM月dd日"));
        subtitle1.setPosition(RectangleEdge.TOP);
        subtitle1.setHorizontalAlignment(HorizontalAlignment.RIGHT);
        jfreechart.addSubtitle(subtitle1);


        CategoryPlot plot = (CategoryPlot)jfreechart.getPlot();
        plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 20.0));

        plot.setDrawSharedDomainAxis(true);
        plot.setRangePannable(true);
        plot.setRangeGridlinesVisible(true);
        plot.setDomainGridlinesVisible(true);
        plot.setRangeZeroBaselineVisible(true);
        plot.setDomainAxis(new CustomCategoryAxis());
        CategoryAxis domainAxis = plot.getDomainAxis();
        domainAxis.setTickMarksVisible(false);
        domainAxis.setLowerMargin(0);
        domainAxis.setUpperMargin(0);

        return jfreechart;
    }

    public static JFreeChart createLineChart(String title, String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) {
        Args.nullNotPermitted(orientation, "orientation");
        CategoryAxis categoryAxis = new CategoryAxis(categoryAxisLabel);
        ValueAxis valueAxis = new NumberAxis(valueAxisLabel);
        LineAndShapeRenderer renderer = new LineAndShapeRenderer(true, false);


        CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer){
            protected void drawDomainGridlines(Graphics2D g2, Rectangle2D dataArea) {
                if (this.isDomainGridlinesVisible()) {
                    CategoryAnchor anchor = this.getDomainGridlinePosition();
                    RectangleEdge domainAxisEdge = this.getDomainAxisEdge();
                    CategoryDataset dataset = this.getDataset();
                    if (dataset != null) {
                        CategoryAxis axis = this.getDomainAxis();
                        if (axis != null) {
                            int columnCount = dataset.getColumnCount();
                            for(int c = 0; c < columnCount; ++c) {
                                double xx = axis.getCategoryJava2DCoordinate(anchor, c, columnCount, dataArea, domainAxisEdge);
                                CategoryItemRenderer renderer1 = this.getRenderer();
                                if (renderer1 != null) {
                                    String timeStr = dataset.getColumnKey(c).toString();
                                    if(timeStr.equals("9:30") || timeStr.equals("10:30") || timeStr.equals("11:30")
                                        || timeStr.equals("14:00") || timeStr.equals("15:00")){
                                        renderer1.drawDomainGridline(g2, this, dataArea, xx);
                                    }
                                }
                            }
                        }

                    }
                }
            }
        };
        plot.setOrientation(orientation);
        JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, legend);
        return chart;
    }



    static class CustomCategoryAxis extends CategoryAxis{

        public List refreshTicks(Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) {
            List ticks = new ArrayList();
            if (dataArea.getHeight() > 0.0D && dataArea.getWidth() >= 0.0D) {
                CategoryPlot plot = (CategoryPlot)this.getPlot();
                List categories = plot.getCategoriesForAxis(this);
                double max = 0.0D;
                if (categories != null) {
                    CategoryLabelPosition position = this.getCategoryLabelPositions().getLabelPosition(edge);
                    float r = this.getMaximumCategoryLabelWidthRatio();
                    if ((double)r <= 0.0D) {
                        r = position.getWidthRatio();
                    }

                    float l;
                    if (position.getWidthType() == CategoryLabelWidthType.CATEGORY) {
                        l = (float)this.calculateCategorySize(categories.size(), dataArea, edge);
                    } else if (RectangleEdge.isLeftOrRight(edge)) {
                        l = (float)dataArea.getWidth();
                    } else {
                        l = (float)dataArea.getHeight();
                    }
                    l = 30;
                    int categoryIndex = 0;

                    for(Iterator iterator = categories.iterator(); iterator.hasNext(); ++categoryIndex) {
                        Comparable category = (Comparable)iterator.next();
                        g2.setFont(this.getTickLabelFont(category));
                        TextBlock label = this.createLabel(category, l * r, edge, g2);
                        if (edge != RectangleEdge.TOP && edge != RectangleEdge.BOTTOM) {
                            if (edge == RectangleEdge.LEFT || edge == RectangleEdge.RIGHT) {
                                max = Math.max(max, this.calculateTextBlockWidth(label, position, g2));
                            }
                        } else {
                            max = Math.max(max, this.calculateTextBlockHeight(label, position, g2));
                        }

                        Tick tick = new CategoryTick(category, label, position.getLabelAnchor(), position.getRotationAnchor(), position.getAngle());
                        ticks.add(tick);
                    }
                }

                state.setMax(max);
                return ticks;
            } else {
                return ticks;
            }
        }

        protected AxisState drawCategoryLabels(Graphics2D g2, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge, AxisState state, PlotRenderingInfo plotState) {
            Args.nullNotPermitted(state, "state");
            if (!this.isTickLabelsVisible()) {
                return state;
            } else {
                List ticks = this.refreshTicks(g2, state, plotArea, edge);
                state.setTicks(ticks);
                int categoryIndex = 0;

                for(Iterator iterator = ticks.iterator(); iterator.hasNext(); ++categoryIndex) {
                    CategoryTick tick = (CategoryTick)iterator.next();
                    String timeStr = tick.getCategory().toString();
                    g2.setFont(this.getTickLabelFont(tick.getCategory()));
                    g2.setPaint(this.getTickLabelPaint(tick.getCategory()));
                    CategoryLabelPosition position = this.getCategoryLabelPositions().getLabelPosition(edge);
                    double x0 = 0.0D;
                    double x1 = 0.0D;
                    double y0 = 0.0D;
                    double y1 = 0.0D;
                    if (edge == RectangleEdge.TOP) {
                        x0 = this.getCategoryStart(categoryIndex, ticks.size(), dataArea, edge);
                        x1 = this.getCategoryEnd(categoryIndex, ticks.size(), dataArea, edge);
                        y1 = state.getCursor() - (double)this.getCategoryLabelPositionOffset();
                        y0 = y1 - state.getMax();
                    } else if (edge == RectangleEdge.BOTTOM) {
                        x0 = this.getCategoryStart(categoryIndex, ticks.size(), dataArea, edge);
                        x1 = this.getCategoryEnd(categoryIndex, ticks.size(), dataArea, edge);
                        y0 = state.getCursor() + (double)this.getCategoryLabelPositionOffset();
                        y1 = y0 + state.getMax();
                    } else if (edge == RectangleEdge.LEFT) {
                        y0 = this.getCategoryStart(categoryIndex, ticks.size(), dataArea, edge);
                        y1 = this.getCategoryEnd(categoryIndex, ticks.size(), dataArea, edge);
                        x1 = state.getCursor() - (double)this.getCategoryLabelPositionOffset();
                        x0 = x1 - state.getMax();
                    } else if (edge == RectangleEdge.RIGHT) {
                        y0 = this.getCategoryStart(categoryIndex, ticks.size(), dataArea, edge);
                        y1 = this.getCategoryEnd(categoryIndex, ticks.size(), dataArea, edge);

                        x0 = state.getCursor() + (double)this.getCategoryLabelPositionOffset();
                        x1 = x0 - state.getMax();
                    }
                    Rectangle2D area = new Rectangle2D.Double(x0, y0, x1 - x0, y1 - y0);
                    Point2D anchorPoint = position.getCategoryAnchor().getAnchorPoint(area);
                    TextBlock block = tick.getLabel();

                    if(timeStr.equals("9:30") || timeStr.equals("10:30") || timeStr.equals("11:30")
                            || timeStr.equals("14:00") || timeStr.equals("15:00")){
                        block.draw(g2, (float)anchorPoint.getX(), (float)anchorPoint.getY(), position.getLabelAnchor(), (float)anchorPoint.getX(), (float)anchorPoint.getY(), position.getAngle());
                    }
                    Shape bounds = block.calculateBounds(g2, (float)anchorPoint.getX(), (float)anchorPoint.getY(), position.getLabelAnchor(), (float)anchorPoint.getX(), (float)anchorPoint.getY(), position.getAngle());
                    if (plotState != null && plotState.getOwner() != null) {
                        EntityCollection entities = plotState.getOwner().getEntityCollection();
                        if (entities != null) {
                            String tooltip = this.getCategoryLabelToolTip(tick.getCategory());
                            String url = this.getCategoryLabelURL(tick.getCategory());
                            entities.add(new CategoryLabelEntity(tick.getCategory(), bounds, tooltip, url));
                        }
                    }
                }

                double w;
                if (edge.equals(RectangleEdge.TOP)) {
                    w = state.getMax() + (double)this.getCategoryLabelPositionOffset();//.categoryLabelPositionOffset;
                    state.cursorUp(w);
                } else if (edge.equals(RectangleEdge.BOTTOM)) {
                    w = state.getMax() + (double)this.getCategoryLabelPositionOffset();
                    state.cursorDown(w);
                } else if (edge == RectangleEdge.LEFT) {
                    w = state.getMax() + (double)this.getCategoryLabelPositionOffset();
                    state.cursorLeft(w);
                } else if (edge == RectangleEdge.RIGHT) {
                    w = state.getMax() + (double)this.getCategoryLabelPositionOffset();
                    state.cursorRight(w);
                }

                return state;
            }
        }
    }

    public static void main(String args[])
    {
        Time2Data timeseriesdemo10 = new Time2Data("股市9:30-15:00指數時序圖");
        timeseriesdemo10.pack();
        timeseriesdemo10.setVisible(true);
    }
}

生成圖片效果:

附件源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章