如何从JfreeChart获取[x,y]值以设置鼠标在屏幕上的位置?

huangapple go评论76阅读模式
英文:

How to get [x,y] values from a JfreeChart to set the mouse position on screen?

问题

这个问题是从之前的问题演化而来的[ https://stackoverflow.com/questions/64201748/in-jfreechart-how-to-get-the-x-y-values-of-a-certain-point-on-the-chart ],在@trashgod的提示下,我成功地实现了我想要的效果,这是我的当前代码:

import java.awt.*;
import java.awt.event.*;
// 其他import语句...

public class PriceVolume_Chart extends JPanel implements ChartMouseListener {
    // 类定义部分...

    public PriceVolume_Chart(String Symbol, int Index) {
        // 构造函数部分...
    }

    // 其他方法...

    @Override
    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);
            Out("x = " + x + "  y = " + y);
            xCrosshair.setValue(x);
            yCrosshair.setValue(y);
        }
    }

    // 其他方法...
}

应用程序的界面如下:

如何从JfreeChart获取[x,y]值以设置鼠标在屏幕上的位置?

但我希望它看起来像下面这样:

如何从JfreeChart获取[x,y]值以设置鼠标在屏幕上的位置?

为了实现第二张图片的效果[在交叉点处显示提示],我需要模拟鼠标移动操作,我知道如何使用Robot设置鼠标,但我不知道[x,y]的值是多少,因此我的问题是:如果我知道交叉线的[x,y]坐标,如何将它们转换为鼠标的[x,y]坐标,以便当我设置鼠标到那个位置时,提示会显示出来?我在注释掉的代码中试图实现这个[robot.mouseMove()],但它没有起作用,正确的做法是什么?

英文:

This question evolved from a previous question [ https://stackoverflow.com/questions/64201748/in-jfreechart-how-to-get-the-x-y-values-of-a-certain-point-on-the-chart ], with a hint from @trashgod, I was able to reach the effect I was looking for, here is my current code :

import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import org.jfree.chart.*;
import org.jfree.chart.axis.*;
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;
static Vector<String> Volume_Color_Vector=new Vector();
Robot robot;
public PriceVolume_Chart(String Symbol,int Index)
{
try
{
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();
float[] dash={2f,0f,2f};
BasicStroke bs=new BasicStroke(1,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,1.0f,dash,2f);
xCrosshair=new Crosshair(Double.NaN,Color.black,bs);
xCrosshair.setLabelBackgroundPaint(new Color(0f,0f,0f,1f));
xCrosshair.setLabelFont(xCrosshair.getLabelFont().deriveFont(14f));
xCrosshair.setLabelPaint(new Color(1f,1f,1f,1f));
xCrosshair.setLabelGenerator(new CrosshairLabelGenerator()
{
@Override
public String generateLabel(Crosshair crosshair)
{
long ms=(long)crosshair.getValue();
TimeSeriesDataItem item=null;
for (int i=0;i<Volume_Series.getItemCount();i++)
{
item=Volume_Series.getDataItem(i);
if (ms==item.getPeriod().getFirstMillisecond()) break;
}
long volume=item.getValue().longValue();
return NumberFormat.getInstance().format(volume);
}
});
xCrosshair.setLabelVisible(true);
yCrosshair=new Crosshair(Double.NaN,Color.black,bs);
yCrosshair.setLabelBackgroundPaint(new Color(0f,0f,0f,1f));
yCrosshair.setLabelFont(xCrosshair.getLabelFont().deriveFont(14f));
yCrosshair.setLabelPaint(new Color(1f,1f,1f,1f));
yCrosshair.setLabelVisible(true);
crosshairOverlay.addDomainCrosshair(xCrosshair);
crosshairOverlay.addRangeCrosshair(yCrosshair);
panel.addOverlay(crosshairOverlay);
add(panel);
if (Index!=-1)
{
TimeSeriesDataItem itemX=Volume_Series.getDataItem(Index);
xCrosshair.setValue(itemX.getPeriod().getFirstMillisecond());
TimeSeriesDataItem itemY=Price_series.getDataItem(Index);
yCrosshair.setValue(itemY.getValue().doubleValue());
/*
robot=new Robot();
robot.mouseMove((int)xCrosshair.getValue(),(int)yCrosshair.getValue());
Out(" xCrosshair.getValue() = "+(int)xCrosshair.getValue()+"  yCrosshair.getValue() = "+(int)yCrosshair.getValue());
*/
}
}
catch (Exception e) { e.printStackTrace(); }
}
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,new SimpleDateFormat("yyyy-MM-d"),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);
MyRender Renderer=new MyRender();
Renderer.setShadowVisible(false);
plot.setRenderer(1,Renderer);
DateAxis domainAxis=(DateAxis) plot.getDomainAxis();                     // Consider adjusting the lower margin of the domain axis for symmetry.
domainAxis.setLowerMargin(0.05);
return chart;
}
private void createPriceDataset(String Symbol)
{
String Lines[]=new String[21],Items[],Date;
int Year, Month, Day;
long Volume,Last_Volume=0;
double Price;
Lines[0]="Date,Open,High,Low,Close,Adj Close,Volume";
Lines[1]="2020-07-17,44.110001,44.369999,41.919998,42.509998,42.323395,849700";
Lines[2]="2020-07-20,41.630001,41.680000,39.669998,40.119999,39.943886,1319300";
Lines[3]="2020-07-21,40.880001,42.860001,40.860001,42.270000,42.084450,2070300";
Lines[4]="2020-07-22,41.919998,42.700001,41.090000,42.570000,42.383133,1317600";
Lines[5]="2020-07-23,43.919998,46.389999,43.279999,44.759998,44.563519,1917700";
Lines[6]="2020-07-24,46.500000,46.500000,43.950001,44.410000,44.215057,1384600";
Lines[7]="2020-07-27,44.000000,44.240002,42.610001,43.860001,43.667469,799800";
Lines[8]="2020-07-28,43.389999,44.590000,42.930000,43.020000,42.831158,699700";
Lines[9]="2020-07-29,42.759998,45.590000,42.740002,45.430000,45.230579,826200";
Lines[10]="2020-07-30,44.160000,44.639999,42.959999,44.500000,44.304661,798100";
Lines[11]="2020-07-31,44.330002,44.419998,42.580002,44.360001,44.165276,1037800";
Lines[12]="2020-08-03,44.560001,45.599998,43.419998,44.939999,44.742729,797000";
Lines[13]="2020-08-04,44.900002,45.500000,43.450001,43.540001,43.348877,971100";
Lines[14]="2020-08-05,44.860001,45.389999,43.650002,45.330002,45.131020,902000";
Lines[15]="2020-08-06,45.049999,46.279999,44.330002,45.299999,45.101147,645200";
Lines[16]="2020-08-07,44.849998,46.189999,44.189999,46.150002,45.947418,604900";
Lines[17]="2020-08-10,46.669998,48.410000,46.549999,47.290001,47.082417,960200";
Lines[18]="2020-08-11,49.110001,50.849998,48.799999,48.910000,48.695301,1187700";
Lines[19]="2020-08-12,49.759998,50.009998,47.060001,47.840000,47.630001,752800";
Lines[20]="2020-08-13,46.950001,48.369999,46.459999,47.110001,47.110001,535700";
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);
Volume_Color_Vector.add(Volume>=Last_Volume?"+":"-");
Last_Volume=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);
Out("x = "+x+"  y = "+y);
xCrosshair.setValue(x);
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",9);
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(); } });
}
}
class MyRender extends XYBarRenderer
{
@Override
public Paint getItemPaint(int row,int col)
{
this.setBarAlignmentFactor(0.5);
//    System.out.println(row+" "+col+" "+super.getItemPaint(row,col));
return PriceVolume_Chart.Volume_Color_Vector.elementAt(col).equals("+")?super.getItemPaint(row,col):new Color(0.56f,0.2f,0.5f,1f);
}
}

The app looks like this :

如何从JfreeChart获取[x,y]值以设置鼠标在屏幕上的位置?

But I want it to look like the following :

如何从JfreeChart获取[x,y]值以设置鼠标在屏幕上的位置?

In order to achieve the effect of the 2nd image [ with hint of the Price at the crossing point ], I need to simulate a mouse point action, I know how to set the mouse using a Robot, but I don't know the [x,y] values for that, so my question is : if I know the cross-hair [x,y], how to convert them to the [x,y] for the mouse so when I set the mouse to that position, the hint will show up ? I was trying to achieve that in the commented out code [ robot.mouseMove() ], but it didn't work, what's the right way to do that ?

答案1

得分: 1

按照这里的讨论,从技术上讲,可以调用工具提示,但这也是尴尬和短暂的。或者,考虑下面所示的XYTextAnnotation,它提供了几个优点:

  • 您可以将Annotation定位在数据坐标中。

  • 您可以根据需要控制其图形外观。

  • 您可以在它出现之前避免任何延迟。

  • 您可以通过渲染器的removeAnnotation()方法控制它何时消失。

下面的片段修改createChart()以传递所需的索引并渲染注释。

private JFreeChart createChart(String Symbol, int index) {
    
    XYPlot plot = chart.getXYPlot();
    TimeSeriesDataItem item = Price_series.getDataItem(index);
    double time = item.getPeriod().getFirstMillisecond();
    double price = item.getValue().doubleValue();
    SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-d");
    String s = "Price: "
        + f.format(new Date((long) time)) + ", "
        + NumberFormat.getCurrencyInstance().format(price);
    XYTextAnnotation note = new XYTextAnnotation(s, time, price - 1);
    note.setFont(UIManager.getFont("ToolTip.font"));
    note.setBackgroundPaint(UIManager.getColor("ToolTip.background"));
    note.setTextAnchor(TextAnchor.CENTER_LEFT);
    note.setOutlinePaint(Color.blue);
    note.setOutlineVisible(true);
    plot.getRenderer().addAnnotation(note);
    
    return chart;
}

如何从JfreeChart获取[x,y]值以设置鼠标在屏幕上的位置?

>我希望用户移动鼠标后它能消失。

在您实现的chartMouseMoved()中,调用removeAnnotation(),如上所述;您可以通过在getAnnotations().isEmpty()的结果上进行预测性的删除,以最小化不必要的更新。

@Override
public void chartMouseMoved(ChartMouseEvent cmevent) {
    XYLineAndShapeRenderer r =
        (XYLineAndShapeRenderer) plot.getRenderer();
    if (!r.getAnnotations().isEmpty()) {
        r.removeAnnotation(note);
    }
    
}
英文:

As discussed here, it is technically possible to evoke a tooltip, but it is also awkward and ephemeral. Alternatively, consider a XYTextAnnotation, illustrated below, which offers several advantages:

  • You can position the Annotation in data coordinates.

  • You can control its graphical appearance as desired.

  • You can avoid any delay before it appears.

  • You can control when it disappears using the renderer's removeAnnotation() method.

The fragment below modifies createChart() to pass the desired index and render the annotation.

private JFreeChart createChart(String Symbol, int index) {
…
XYPlot plot = chart.getXYPlot();
TimeSeriesDataItem item = Price_series.getDataItem(index);
double time = item.getPeriod().getFirstMillisecond();
double price = item.getValue().doubleValue();
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-d");
String s = "Price: "
+ f.format(new Date((long) time)) + ", "
+ NumberFormat.getCurrencyInstance().format(price);
XYTextAnnotation note = new XYTextAnnotation(s, time, price - 1);
note.setFont(UIManager.getFont("ToolTip.font"));
note.setBackgroundPaint(UIManager.getColor("ToolTip.background"));
note.setTextAnchor(TextAnchor.CENTER_LEFT);
note.setOutlinePaint(Color.blue);
note.setOutlineVisible(true);
plot.getRenderer().addAnnotation(note);
…
return chart;
}

如何从JfreeChart获取[x,y]值以设置鼠标在屏幕上的位置?

>I'd like it to disappear once user moves the mouse.

In your implementation of chartMouseMoved(), invoke removeAnnotation(), as suggested above; you can minimize unnecessary updates by predicating the removal on the result of getAnnotations().isEmpty().

@Override
public void chartMouseMoved(ChartMouseEvent cmevent) {
XYLineAndShapeRenderer r =
(XYLineAndShapeRenderer) plot.getRenderer();
if (!r.getAnnotations().isEmpty()) {
r.removeAnnotation(note);
}
…
}

答案2

得分: 1

import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import org.jfree.chart.*;
import org.jfree.chart.annotations.*;
import org.jfree.chart.axis.*;
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.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.chart.ui.*;

public class PriceVolume_Chart extends JPanel implements ChartMouseListener {
    // ... (Please note: I'm only providing a partial translation of the code)
    // ... (The translation below includes the class definition and imports)
}

class MyRender extends XYBarRenderer {
    // ... (Please note: I'm only providing a partial translation of the code)
    // ... (The translation below includes the class definition and imports)
}

Please note that the provided translation includes only a portion of the code due to its length. If you need the full translation or if you have specific questions about parts of the code, feel free to ask.

英文:

Alright, thanks to @trashgod, I came up with the following code.

(1) It would show info at start up, but after user moves mouse, it will disappear and show info at new mouse location:

plot.getRenderer().removeAnnotation(note);

(2) It's also smart enough to avoid left and right edge, so annotation won't be cut off at the left and right side of the chart.

note.setTextAnchor(Index<Volume_Color_Vector.size()/2
?TextAnchor.TOP_LEFT:TextAnchor.TOP_RIGHT);

Complete code:

import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import org.jfree.chart.*;
import org.jfree.chart.annotations.*;
import org.jfree.chart.axis.*;
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.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.chart.ui.*;
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;
static Vector<String> Volume_Color_Vector=new Vector();
XYTextAnnotation note;
XYPlot plot;
XYLineAndShapeRenderer r;
public PriceVolume_Chart(String Symbol,int Index)
{
try
{
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();
float[] dash={2f,0f,2f};
BasicStroke bs=new BasicStroke(1,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,1.0f,dash,2f);
xCrosshair=new Crosshair(Double.NaN,Color.black,bs);
xCrosshair.setLabelBackgroundPaint(new Color(0f,0f,0f,1f));
xCrosshair.setLabelFont(xCrosshair.getLabelFont().deriveFont(14f));
xCrosshair.setLabelPaint(new Color(1f,1f,1f,1f));
xCrosshair.setLabelGenerator(new CrosshairLabelGenerator()
{
@Override
public String generateLabel(Crosshair crosshair)
{
long ms=(long)crosshair.getValue();
TimeSeriesDataItem item=null;
for (int i=0;i<Volume_Series.getItemCount();i++)
{
item=Volume_Series.getDataItem(i);
if (ms==item.getPeriod().getFirstMillisecond()) break;
}
long volume=item.getValue().longValue();
return NumberFormat.getInstance().format(volume);
}
});
xCrosshair.setLabelVisible(true);
yCrosshair=new Crosshair(Double.NaN,Color.black,bs);
yCrosshair.setLabelBackgroundPaint(new Color(0f,0f,0f,1f));
yCrosshair.setLabelFont(xCrosshair.getLabelFont().deriveFont(14f));
yCrosshair.setLabelPaint(new Color(1f,1f,1f,1f));
yCrosshair.setLabelVisible(true);
crosshairOverlay.addDomainCrosshair(xCrosshair);
crosshairOverlay.addRangeCrosshair(yCrosshair);
panel.addOverlay(crosshairOverlay);
add(panel);
if (Index!=-1 && Index<Volume_Series.getItemCount())
{
TimeSeriesDataItem itemX=Volume_Series.getDataItem(Index);
xCrosshair.setValue(itemX.getPeriod().getFirstMillisecond());
TimeSeriesDataItem itemY=Price_series.getDataItem(Index);
yCrosshair.setValue(itemY.getValue().doubleValue());
TimeSeriesDataItem item=Price_series.getDataItem(Index);
double time=item.getPeriod().getFirstMillisecond();
double price=item.getValue().doubleValue();
SimpleDateFormat f=new SimpleDateFormat("yyyy-MM-d");
String st=" Price : "+f.format(new Date((long)time))+" , "+NumberFormat.getCurrencyInstance().format(price)+" ";
note=new XYTextAnnotation(st,time,price-1);
note.setFont(UIManager.getFont("ToolTip.font"));
note.setBackgroundPaint(UIManager.getColor("ToolTip.background"));
note.setTextAnchor(Index<Volume_Color_Vector.size()/2?TextAnchor.TOP_LEFT:TextAnchor.TOP_RIGHT);
note.setOutlinePaint(Color.blue);
note.setOutlineVisible(true);
plot.getRenderer().addAnnotation(note);
}
}
catch (Exception e) { e.printStackTrace(); }
}
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);
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,new SimpleDateFormat("yyyy-MM-d"),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);
MyRender Renderer=new MyRender();
Renderer.setShadowVisible(false);
plot.setRenderer(1,Renderer);
DateAxis domainAxis=(DateAxis) plot.getDomainAxis();                     // Consider adjusting the lower margin of the domain axis for symmetry.
domainAxis.setLowerMargin(0.05);
r=(XYLineAndShapeRenderer)plot.getRenderer();
return chart;
}
private void createPriceDataset(String Symbol)
{
String Lines[]=new String[21],Items[],Date;
int Year, Month, Day;
long Volume,Last_Volume=0;
double Price;
Lines[0]="Date,Open,High,Low,Close,Adj Close,Volume";
Lines[1]="2020-07-17,44.110001,44.369999,41.919998,42.509998,42.323395,849700";
Lines[2]="2020-07-20,41.630001,41.680000,39.669998,40.119999,39.943886,1319300";
Lines[3]="2020-07-21,40.880001,42.860001,40.860001,42.270000,42.084450,2070300";
Lines[4]="2020-07-22,41.919998,42.700001,41.090000,42.570000,42.383133,1317600";
Lines[5]="2020-07-23,43.919998,46.389999,43.279999,44.759998,44.563519,1917700";
Lines[6]="2020-07-24,46.500000,46.500000,43.950001,44.410000,44.215057,1384600";
Lines[7]="2020-07-27,44.000000,44.240002,42.610001,43.860001,43.667469,799800";
Lines[8]="2020-07-28,43.389999,44.590000,42.930000,43.020000,42.831158,699700";
Lines[9]="2020-07-29,42.759998,45.590000,42.740002,45.430000,45.230579,826200";
Lines[10]="2020-07-30,44.160000,44.639999,42.959999,44.500000,44.304661,798100";
Lines[11]="2020-07-31,44.330002,44.419998,42.580002,44.360001,44.165276,1037800";
Lines[12]="2020-08-03,44.560001,45.599998,43.419998,44.939999,44.742729,797000";
Lines[13]="2020-08-04,44.900002,45.500000,43.450001,43.540001,43.348877,971100";
Lines[14]="2020-08-05,44.860001,45.389999,43.650002,45.330002,45.131020,902000";
Lines[15]="2020-08-06,45.049999,46.279999,44.330002,45.299999,45.101147,645200";
Lines[16]="2020-08-07,44.849998,46.189999,44.189999,46.150002,45.947418,604900";
Lines[17]="2020-08-10,46.669998,48.410000,46.549999,47.290001,47.082417,960200";
Lines[18]="2020-08-11,49.110001,50.849998,48.799999,48.910000,48.695301,1187700";
Lines[19]="2020-08-12,49.759998,50.009998,47.060001,47.840000,47.630001,752800";
Lines[20]="2020-08-13,46.950001,48.369999,46.459999,47.110001,47.110001,535700";
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);
Volume_Color_Vector.add(Volume>=Last_Volume?"+":"-");
Last_Volume=Volume;
}
}
@Override
public void chartMouseClicked(ChartMouseEvent event)
{
// ignore
}
public void chartMouseMoved(ChartMouseEvent cmevent)
{
ChartEntity chartentity=cmevent.getEntity();
if (chartentity instanceof XYItemEntity)
{
if (!r.getAnnotations().isEmpty()) r.removeAnnotation(note);
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);
Out("x = "+x+"  y = "+y);
xCrosshair.setValue(x);
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",9);
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(); } });
}
}
class MyRender extends XYBarRenderer
{
@Override
public Paint getItemPaint(int row,int col)
{
this.setBarAlignmentFactor(0.5);
//    System.out.println(row+" "+col+" "+super.getItemPaint(row,col));
return PriceVolume_Chart.Volume_Color_Vector.elementAt(col).equals("+")?super.getItemPaint(row,col):new Color(0.56f,0.2f,0.5f,1f);
}
}

如何从JfreeChart获取[x,y]值以设置鼠标在屏幕上的位置?

huangapple
  • 本文由 发表于 2020年10月6日 08:39:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/64217855.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定