如何在JFreeChart中显示十字线和红色以表示价格下降? [英] How to show cross lines and red color for price drop in JFreeChart?

查看:64
本文介绍了如何在JFreeChart中显示十字线和红色以表示价格下降?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序简化如下:

My app is simplified below :

import java.awt.*;
import java.awt.event.*;
import java.text.*;
import javax.swing.*;
import org.jfree.chart.*;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.entity.*;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.data.time.*;
import org.jfree.data.xy.XYDataset;
import org.jfree.chart.labels.*;
import org.jfree.chart.panel.*;
import org.jfree.chart.plot.*;

public class PriceVolume_Chart extends JPanel implements ChartMouseListener    // A demo application for price-volume chart.   
{
  ChartPanel panel;
  TimeSeries Price_series=new TimeSeries("Price");
  TimeSeries Volume_Series=new TimeSeries("Volume");
  Crosshair xCrosshair,yCrosshair;
  
  public PriceVolume_Chart(String Symbol)
  {
    JFreeChart chart=createChart(Symbol);
    panel=new ChartPanel(chart,true,true,true,false,true);
    panel.setPreferredSize(new java.awt.Dimension(1000,500));
    panel.addChartMouseListener(this);
    CrosshairOverlay crosshairOverlay=new CrosshairOverlay();
    xCrosshair=new Crosshair(Double.NaN,Color.GRAY,new BasicStroke(0f));
    xCrosshair.setLabelVisible(true);
    yCrosshair=new Crosshair(Double.NaN,Color.GRAY,new BasicStroke(0f));
    yCrosshair.setLabelVisible(true);
    crosshairOverlay.addDomainCrosshair(xCrosshair);
    crosshairOverlay.addRangeCrosshair(yCrosshair);
    panel.addOverlay(crosshairOverlay);
    add(panel);
  }

  private JFreeChart createChart(String Symbol)
  {
    createPriceDataset(Symbol);
    XYDataset priceData=new TimeSeriesCollection(Price_series);
    JFreeChart chart=ChartFactory.createTimeSeriesChart(Symbol,
                                                        "Date",
                                                        getYLabel("Price ( $ )"),
                                                        priceData,
                                                        true,
                                                        true,
                                                        true
                                                       );
    XYPlot plot=chart.getXYPlot();
    plot.setBackgroundPaint(new Color(192,196,196));
    NumberAxis rangeAxis1=(NumberAxis)plot.getRangeAxis();
    rangeAxis1.setLowerMargin(0.40);                                           // Leave room for volume bars
//    plot.getRenderer().setDefaultToolTipGenerator(new StandardXYToolTipGenerator(StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT,DateFormat.getDateInstance(), NumberFormat.getCurrencyInstance()));
    plot.getRenderer().setDefaultToolTipGenerator(new StandardXYToolTipGenerator(StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT,new SimpleDateFormat("yyyy-MM-d"),NumberFormat.getCurrencyInstance()));
//    DecimalFormat format=new DecimalFormat("00.00");
//    rangeAxis1.setNumberFormatOverride(format);
//    rangeAxis1.setNumberFormatOverride(NumberFormat.getCurrencyInstance());  

    NumberAxis rangeAxis2=new NumberAxis("Volume");
    rangeAxis2.setUpperMargin(1.00);                                           // Leave room for price line   
    rangeAxis2.setNumberFormatOverride(NumberFormat.getNumberInstance());
    plot.setRangeAxis(1,rangeAxis2);
    plot.setDataset(1,new TimeSeriesCollection(Volume_Series));
    plot.setRangeAxis(1,rangeAxis2);
    plot.mapDatasetToRangeAxis(1,1);
    XYBarRenderer renderer2=new XYBarRenderer(0.20);
    renderer2.setShadowVisible(false);
    renderer2.setDefaultToolTipGenerator(new StandardXYToolTipGenerator(StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT,new SimpleDateFormat("yyyy-MM-d"),new DecimalFormat("0,000")));
    plot.setRenderer(1,renderer2);
    return chart;
  }

  private void createPriceDataset(String Symbol)
  {
    String Lines[]=new String[21],Items[],Date;
    int Year,Month,Day;
    long Volume;
    double Price;

    Lines[0]="Date,Open,High,Low,Close,Adj Close,Volume";
    Lines[1]="2019-09-23,129.589996,130.710007,128.240005,129.300003,126.555969,553700";
    Lines[2]="2019-09-24,129.309998,129.529999,125.500000,126.750000,124.060089,732900";
    Lines[3]="2019-09-25,126.570000,128.500000,126.190002,127.879997,125.166100,422000";
    Lines[4]="2019-09-26,127.849998,128.589996,127.169998,127.779999,125.068230,376100";
    Lines[5]="2019-09-27,128.669998,129.289993,126.389999,126.419998,123.737083,332900";
    Lines[6]="2019-09-30,126.589996,128.789993,125.849998,128.130005,125.410797,456700";
    Lines[7]="2019-10-01,129.039993,130.899994,125.480003,126.040001,123.365158,322700";
    Lines[8]="2019-10-02,125.059998,125.180000,121.620003,123.120003,120.507126,577100";
    Lines[9]="2019-10-03,122.650002,123.320000,119.089996,122.559998,119.959007,581300";
    Lines[10]="2019-10-04,122.970001,123.949997,121.320000,123.879997,121.250992,315700";
    Lines[11]="2019-10-07,123.139999,124.610001,122.669998,122.879997,120.272217,510300";
    Lines[12]="2019-10-08,121.720001,121.879997,118.089996,118.660004,116.141777,616600";
    Lines[13]="2019-10-09,119.410004,119.610001,116.680000,118.419998,115.906868,603300";
    Lines[14]="2019-10-10,119.089996,121.209999,117.080002,118.209999,115.701324,483300";
    Lines[15]="2019-10-11,120.330002,123.040001,119.720001,122.550003,119.949226,700500";
    Lines[16]="2019-10-14,122.550003,123.720001,120.940002,122.540001,119.939430,492900";
    Lines[17]="2019-10-15,122.849998,124.220001,121.230003,123.699997,121.074814,598200";
    Lines[18]="2019-10-16,123.889999,124.849998,122.800003,123.209999,120.595207,663600";
    Lines[19]="2019-10-17,123.449997,124.889999,122.790001,123.360001,120.742035,563200";
    Lines[20]="2019-10-18,123.050003,124.620003,122.459999,123.540001,120.918213,650300";
    
    for (int i=1;i<Lines.length;i++)
    {
      Items=Lines[i].split(",");
      Date=Items[0].replace("-0","-");
      Price=Double.parseDouble(Items[5]);
      Volume=Long.parseLong(Items[6]);
      Items=Date.split("-");
      Year=Integer.parseInt(Items[0]);
      Month=Integer.parseInt(Items[1]);
      Day=Integer.parseInt(Items[2]);
      Price_series.add(new Day(Day,Month,Year),Price);
      Volume_Series.add(new Day(Day,Month,Year),Volume);
    }
  }

  @Override
  public void chartMouseClicked(ChartMouseEvent event)
  {
    // ignore
  }

  public void chartMouseMoved(ChartMouseEvent cmevent)
  {
    ChartEntity chartentity=cmevent.getEntity();
    if (chartentity instanceof XYItemEntity)
    {
      XYItemEntity e=(XYItemEntity)chartentity;
      XYDataset d=e.getDataset();
      int s=e.getSeriesIndex();
      int i=e.getItem();
      double x=d.getXValue(s,i);
      double y=d.getYValue(s,i);
      this.xCrosshair.setValue(x);
      this.yCrosshair.setValue(y);
    }
  }
  String getYLabel(String Text)
  {
    String Result="";
    
    for (int i=0;i<Text.length();i++) Result+=Text.charAt(i)+(i<Text.length()-1?"\u2009":"");
//    Out(Result);
    return Result;
  }

  private static void out(String message) { System.out.print(message); }
  private static void Out(String message) { System.out.println(message); }

  // Create the GUI and show it. For thread safety, this method should be invoked from the event-dispatching thread.
  static void Create_And_Show_GUI()
  {
    final PriceVolume_Chart demo=new PriceVolume_Chart("ADS");

    JFrame frame=new JFrame("PriceVolume_Chart Frame");
    frame.add(demo);
    frame.addWindowListener( new WindowAdapter()
    {
      public void windowActivated(WindowEvent e) { }
      public void windowClosed(WindowEvent e) { }
      public void windowClosing(WindowEvent e) { System.exit(0); }
      public void windowDeactivated(WindowEvent e) { }
      public void windowDeiconified(WindowEvent e) { demo.repaint(); }
      public void windowGainedFocus(WindowEvent e) { demo.repaint(); }
      public void windowIconified(WindowEvent e) { }
      public void windowLostFocus(WindowEvent e) { }
      public void windowOpening(WindowEvent e) { demo.repaint(); }
      public void windowOpened(WindowEvent e) { }
      public void windowResized(WindowEvent e) { demo.repaint(); }
      public void windowStateChanged(WindowEvent e) { demo.repaint(); }
    });
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }

  public static void main(String[] args)
  {
    // Schedule a job for the event-dispatching thread : creating and showing this application's GUI.
    SwingUtilities.invokeLater(new Runnable() { public void run() { Create_And_Show_GUI(); } });
  }
}

================================================ =====================

=====================================================================

在@trashgod的帮助下,我可以将十字线添加到图表中.但是我仍然想知道如何实现以下目标:

With the help of @trashgod I was able to add the cross-hair to the chart. However I still want to know how to achieve the following :

 [1] The value shown for volume when cross-hair moves, is in-correct, how to show correct volume value ?
 [2] How to have solid non-transparent background for the dynamic values shown near the axis ? Now it's transparent, hard to read.
 [3] How to set the cross-hair at startup on a certain [ e.g. 20th ] date ?
 [4] How to show red color for volumes when price drops ?

以下是我正在寻找的图像:

Here is an image of what I'm looking for :

推荐答案

当鼠标指向图像上的不同位置时显示交叉线吗?

Show cross lines when my mouse points to different locations on the image?

您能够采用 CrosshairOverlayDemo1 中显示的方法,建议使用

十字准线移动时显示的音量值不正确,如何显示正确的音量值?

The value shown for volume when cross-hair moves, is incorrect, how to show correct volume value?

您实现的ChartMouseListener从价格数据集中访问 x y 值. x 值是日期; y 值是价格.如果没有格式化,则十字准线会正确显示 epoch 的毫秒数.您可能想要获取相应的卷.

Your implementation of ChartMouseListener accesses the x and y values from the price dataset. The x value is the date; the y value is the price. Absent formatting, the crosshair correctly displays the number of milliseconds from the epoch. You probably want to fetch the corresponding volume.

如何为轴附近显示的动态值提供坚实的非透明背景?现在它是透明的,很难阅读.

How to have solid non-transparent background for the dynamic values shown near the axis? Now it's transparent, hard to read.

您可以修改十字准线的外观,如此处所示.对于背景,请使用不透明的颜色或将alpha值指定为255以构造纯色.

You can modify the crosshair's appearance as shown here. For the background, use an opaque color or specify an alpha value of 255 to construct a solid color.

如何在特定情况下(例如)在启动时设置十字准线20日约会?

How to set the cross-hair at startup on a certain e.g. 20th date?

您可以使用Robot,如此处所示,但我不希望以这种方式使用户感到惊讶.

You can use Robot, as shown here, but I prefer not to surprise the user in this way.

价格下跌时,如何显示红色的数量?

How to show red color for volumes when price drops?

您可以覆盖getItemPaint(),如此处此处所示,以根据体积更改渲染的颜色.

You can override getItemPaint(), as shown here here to change the rendered color as a function of the volume.

通常,您会发现像与十字准线叠加演示一样,在可以集成到您的代码中的孤立示例中更容易研究此类问题.

In general, you'll find it easier to examine such issues in isolated examples that can be integrated into your code, as you did with the crosshair overlay demo.

这篇关于如何在JFreeChart中显示十字线和红色以表示价格下降?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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