ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  How to synchronize DrawArea drawing with ChartViewer viewPort
Posted by Jianhua on Mar-25-2019 10:07
Attachments:
Hi Sir,
I am using Java version ChartDirector. I have setup a finance chart , and used drawArea to
draw some lines , but I have some problem here, I hope anyone can help.
1. When I use mouse listener to click a button, the lines will draw on the original finance chart, but when I zoom in or zoom out or scroll, the lines drew by DrawArea method will disappear. How could I synchronize the lines drew by DreaArea function wih ChartViewer viewport? Means if I zoom in or out the chart, the DrawArea lines still keep with the original finance chart. Please provide some code samples.

2. Some portion of arc which drew by DrawArea function are outside of the plot area, means the right side of the plot area space is not enough for the  whole picture, I want the whole picture show on my chart, of course I don't think I should use setClipping. I want the right side space of the chart dynamically increase when the drawing needed. How can I do that ? please provide some code samples.

3. When I draw a price target line on finance chart with DrawArea function, it works fine, but some horizontal lines are higher than Y axis maximum range or lower than Y axis minimum range, how could I show the lines with scroll bar or anyother method? please provide some code samples.

please take a look at the attached files.

The first and 2nd files are representing problems, the 3rd file is a correctly showing.
I hope to hear from you soon.
Thanks.
fibnode1.PNG
fibnode2.PNG
fibnode3.PNG

  Re: How to synchronize DrawArea drawing with ChartViewer viewPort
Posted by Peter Kwan on Mar-26-2019 05:52
Hi Jianhua,

1. When you use the mouse to draw lines, your code will need to store the data coordinates of the starting and ending points of the lines, so that your code can redraw the lines when the chart is updated.

The coordinates from the mouse is pixel coordinates. You may use XYChart.getXValue and XYChart.getYValue to get the data coordinates. Note that the x data coordinate is the array index relative to the first candlestick. Because your code already knows the array index of the first candlestick, it can determine the array index of the end points of the line.

When you update the chart, your code can compute the new x data coordinates for the end points, and convert the data coordinates to pixel coordinates XYChart.getXCoor and XYChart.getYCoor. In this way, you can redraw them with the DrawArea.

It is possible for the chart to scroll so that one end point of the line is outside plotarea, while the other end point is inside the plotarea, so you may need to use DrawArea.setClipRect if you do not want the chart to draw outside the plotarea.

2. I notice in your chart, there are already some gap at the right side. I am not sure how you create the gap. Two methods I can think of is by using Axis.setMargin or by adding dummy entries to the timeStamps array.

Since the arc and text is drawn by your code, your code should know the coordinates, and it should be able to determine if it is outside the plot area. If this is the case, your code can increase the gap to keep the drawing inside.

3. If the axis is auto-scaled by ChartDirector, you can configure it so that the scale is larger than necessary so as to leave some space at the top. For example, in your attached image, the y-axis scale is 4 to 50. If it is changed to 4 to 60, there will be some space left for the text. You can use Axis.setAutoScale to do this. For example:

// reserve 15% space on top
myMainPriceChart.yAxis().setAutoScale(0.15, 0, 0);

If the axis scale is not auto-scaled by ChartDirector, but is set by your code, then your code can extend the axis scale to reserve space.

Hope this can help.

Regards
Peter Kwan

  Re: How to synchronize DrawArea drawing with ChartViewer viewPort
Posted by Jianhua on Mar-26-2019 09:55
Hi Peter,
Thanks a lot for the quick reply! I have read your reply twice, but still not very sure how to solve my problem.
1. I noticed that my chartViewer view port change event does not monitor the lines and arc drawings which drew by DrawArea method. My code use the same code of the ZoomScrollDemo3 sample code(in java edition). So my chart has a zoom and scroll function, but after I draw the lines and arcs with DrawArea method, if I zoom in or out, the lines and arcs just gone. This is the main problem. My code Logic is like this:
a. initialize the GUI (the code includes  chartViewer1.updateViewPort(true, true), it will draw the chart , this chart is a finance chart with pure price and volume bars without the arcs and custom lines drawing).
b. I click and choose two price points on the chart with hotspot mouse clicked event, When I click a button on my toolbar(it named "fibnodes“), it will call the DrawFibnodes() method, then all the Fibnodes lines and arcs will appear on my chart. So far so good, but my DrawFibnodes() method is called by the "fibndoes Button" clicked mouse event, the drawing code is not inside the  DrawChart() method which is to draw the original price and volume pure chart.
means the DrawChart() method and DrawFibnodes() method are two seperate methods.
But the chartViewer viewport updates only the DrawChart() method, it just ignored my DrawFibnodes() method when zooming triggeres a viewport update event. How can I include the DrawFibnodes() method to viewPort Update event? I have tried to use a code line like this : chartViewer1.setChart(x); "x" is the XYChart object inside the DrawFibnodes() method, but there's a error said "can not cast to XYChart", something like that, what does that mean? . My code already computes the X coordinate and Y coordinate for the lines and arcs and stores inside ArrayList, but the problem is when I zoom the chart, will the X, Y Coordinate change? Do I have to re-calculate the X and Y coordinate?  Could you provide some ideas?

2. I use XYChart.YAxis().setMargin() to reserved some space on right side of the chart. Now my problem is only half solved, not perfect.  My code Logic is like this:
a. I choose several price points, then click the "Fibnodes" button on toolbar, if the right margin of the chart is enough, it will draw the lines and arcs normally.
b. If the right margin of chart is not enough, it will pop up a message box" the space not enough, please redraw the chart.", then the chart will redraw with a larger right side margin.
c. I have to click and choose price points again, then call DrawFibnodes() method again to draw the lines and arcs.  it solved the problem, but not perfect. Do you have a better way to do it? Could You fine tune my code logic?

3. I use the same solution to deal with the price Objective lines (those lines named COP, OP, XOP in my previous post message) problem, I use XYChart.YAxis().setLinearScale() method to increase the top margin of the chart, but the chart is squeezed after set the Y axis, so I wanted to use a better method that is using a scroll bar on the right side of the chart, in this way the chart will be not squeezed and still can show the XOP lines. Means the XOP lines will draw outside of the plot area, but I can use scrollbar to scroll up and still can see the XOP lines and information related with the line. How could I do this?

Really appreciate Your help, I learned a lot from your forum.
I hope to hear from you soon.
Regards,
Jianhua

  Re: How to synchronize DrawArea drawing with ChartViewer viewPort
Posted by Peter Kwan on Mar-27-2019 06:42
Attachments:
Hi Jianhua,

1. The viewportchange event is like a mouse event. By default, it does not do anything. You have to put code in the event handler to redraw the chart.

if (e.needUpdateChart())
    drawChart(chartViewer1);

If you want the ViewPortChanged to update the Fibnodes lines as well, you can add code to draw Fibnodes lines as well:

if (e.needUpdateChart())
{
    drawChart(chartViewer1);
    DrawFibnodes();
}

However, since drawChart and DrawFibnodes must be used together, so it is easier just put DrawFibnodes inside the drawChart just before the chartViewer1.setChart, like:

DrawFibnodes(chartViewer1, mainChart);
chartViewer1.setChart(c);

I have attached a simple example for your reference. When you click two points on the FinanceChart, it will draw a line connecting the two points. You can zoom/scroll the chart, and the line will move with the chart.

2. I would do it this way.

a. Determine how much space the DrawFibnodes needs.

b. Call XYChart.YAxis().setMargin() to reserve the space.

c. Draw the chart.


3. You can always put a vertical scrollbar on the screen. When the user moves the scrollbar, you can modify the y-axis scale and redraw the chart. For example, if the y-axis scale is originally 10 - 100, you can change it to 30 - 120. In this way, the chart contents will be moved down.

Hope this can help.

Regards
Peter Kwan
ZoomScrollDemo3.java
ZoomScrollDemo3.java

13.41 Kb

  Re: How to synchronize DrawArea drawing with ChartViewer viewPort
Posted by Jianhua on Mar-27-2019 13:17
Attachments:
Hi Peter,
Thanks a lot for your reply! I will test your ideas and look into the sampe code.
I have modified my code and insert the DrawFibnodes() method to viewPort change event method. Yes, the view port updates the DrawFibnodes lines and arcs , but the X coordinate of the lines and arcs changed position after zoomming. PLease see the attached screen shot.  The first picture  is before zooming, the 2nd is after zooming. That means I have to re-calculate the X Coordinate of the lines, but I have no idea how to do it. How Could I solve this problem?
I hope to hear from you soon.
Regards,
Jianhua
Normal.PNG
Abnormal.PNG

  Re: How to synchronize DrawArea drawing with ChartViewer viewPort
Posted by Peter Kwan on Mar-27-2019 14:50
Hi Jianhua,

The coordinates from mouse click is pixel coordinates. You need to convert them to data coordinates for storage.

When you draw the fib nodes, you need to convert them back to pixel coordinates using the updated chart, and draw them.

The point (1) in my previous message on Mar-26-2019 explains in more details.

https://www.chartdir.com/forum/download_thread.php?site=chartdir&bn=chartdir_support&thread=1553479653#N1553550755

The sample code I attached in my last message contains the code to do the above. Please look at the code in "chartViewer1_onMouseClick" to see how the mouse coordinates are convert to data coordinates using XYChart.getXValue and XYChart.getYValue. In drawCustomLine, the data coordinates are converted back to pixel coordinates using XYChart.getXCoor and XYChart.getYCoor based on the updated chart.

You mention about "ZoomScrollDemo3". It does not seem to be a sample code included in the ChartDirector distribution. May be it is a sample code posted in the forum sometime ago. The "ZoomScrollDemo3" sample code I attached is based on ChartDirector version 6, and it uses the array index as the x-coordinates, not date/time.

A financial chart can skip some date/time randomly. For example, if there is a typhoon or hurricane, the stock exchange may need to stop trading for one day. In this case, the day is skipped. Since the date/time is random, it is not suitable to be used as x-coordinates. The correct x-coordinate is the trading session number. In programming, you can use the array index as the trading session number. The date/time is treated as "names" for human reading only.

Since the drawChart and DrawFibNodes must be executed together, so in my sample code, I just insert the drawCustomLines into the drawChart code, just before the line "chartViewer1.setChart(c);". It is like:


private void drawChart(ChartViewer viewer)
{
    .... draw chart as usual ....

    // add custom lines
    drawCustomLine(chartViewer1, mainChart);

    // display the chart
    chartViewer1.setChart(c);
}


With the above method, it only needs to call "setChart" once. (There is no need to call "setChart" in the drawCustomLine.) So the display will not be updated twice.

In the drawCustomLine, the DrawArea is obtained using "DrawArea d = mainChart.makeChart3();" to make sure it draws on top of the chart contents, not under it.


Regards
Peter Kwan

  Re: How to synchronize DrawArea drawing with ChartViewer viewPort
Posted by Jianhua on Mar-27-2019 19:20
Hi Peter,
Thanks a lot for the quick reply! I understood your idea that I should insert the DrawFibnodes() method into the DrawChart() method, and draw the custom lines together, but practically I should not do that.  Because My application works like this:
1. Load the stock price and volume data, layout the finance chart, the fincance chart will appear first.
2. Then I click and choose at least 2 or more price points on the finance chart(inside the plot area), I use the hotspot clicked method to get the X and Y coordinate of the price points and add them to a LinkedList named "highLowXCoor" and "highLowYCoor", and at the same time get the high price and low price, then add them to a LinkedList "fibList". The hotspot clicked method is below:

private void chartViewer1_HotSpotClicked(HotSpotEvent e)
   {
   // We show the pop up dialog only when the mouse action is not in zoom-in or zoom-out mode.
   if ((chartViewer1.getMouseUsage() != Chart.MouseUsageZoomIn) &&
   (chartViewer1.getMouseUsage() != Chart.MouseUsageZoomOut)) {
   //showHotSpotParam(e);  
   double fibValue=0;
//get the focus,reactions or A,B,C list  
fibValue=getFibList((MultiChart)chartViewer1.getChart(),     chartViewer1.getPlotAreaMouseX(),chartViewer1.getPlotAreaMouseY());
if(fibValue==0) return;
fibList.add(fibValue);
int xCoor=getXCoorForReaction((MultiChart)chartViewer1.getChart(), chartViewer1.getPlotAreaMouseX());
xCoorForReaction.add(xCoor);
   }
   }

I have a method getXCoorForReaction() to get the X coordinate for reaction price points.
3.When all the above done, I click a button inside the ToolBar named "fibNodes Button", then only at this point the fibnodes lines and arcs will draw on the chart. So I could not put the DrawFibnodes() method into the DrawChart() method.

The sample code "zoomAndScrollsample3" is the latest version sample included in the latest ChartDirector java version. I compared the code with yours, it's almost the same except yours is simpler.
I hope you can fully understand my application working sequence : the chart comes out first, then click price points on the chart, then click the fibnodes button(on Tool menu bar), then it calls the DrawFibnodes() method, then the drawing completed. So in this scenario, how can I move the horizontal scroll bar or zooming and fibnodes drawing still updates together with the finance original chart?

I hope to hear from your soon.
Regards,
Jianhua

  Re: How to synchronize DrawArea drawing with ChartViewer viewPort
Posted by Jianhua on Mar-27-2019 19:35
Hi Peter,
In addition to my last message, to draw a fibnodes series, I need a focus number which is the highest high of the current visible chart, one or more reactions numbers which are low prices of the current visible chart. This is for the uptrend case, just for example.  In your sample code, it only need to convert the point value to X and Y coordinate, I knew how to get the X and Y coordinate, but after I zoom the chart, the previous X and Y coordinate of the high and low price are not  same as the current ones. I think this is the problem why the chart showing incorrect position.

Regards,
Jianhua

  Re: How to synchronize DrawArea drawing with ChartViewer viewPort
Posted by Peter Kwan on Mar-28-2019 16:00
Hi Jianhua,

If I were you, I would put the DrawFibnodes inside drawChart. Initially, the "LinkedList" should be empty, so the DrawFibnodes should not do anything, and it will not affect the initial drawChart. the DrawFibnodes should draw things only if there are data in the "LinkedList".

In my ZoomScrollDemo3 example, initially there is only the chart. After the user clicks two points, it will display the custom line. This is similar to your case. But I still put the drawCustomLine inside drawChart. Initially, the user has not clicked on any point, so there is no data, and the drawCustomLine would not draw thing. So initially, there is just the chart. Only when the user clicks two points will the drawCustomLine draws the line.

For your case, because the DrawFibnodes depends on the "highest high" and "lowest low" of the current chart, it is even better to put DrawFibnodes inside drawChart. It is because during drawChart, you can determine the "highest high" and "lowest low", and then pass them as parameters to the DrawFibnotes code. So the DrawFibnotes will always use the most updated "highest high" and "lowest low".

For all the pixel coordinates such as chartViewer1.getPlotAreaMouseX() and chartViewer1.getPlotAreaMouseY(), please do not store them directly. Convert them to data values first, and store the data values. In DrawFibnodes, it should convert the data values back to pixel coordinates and draw them.

For the fibNodes Button, when it is clicked, please call chartViewer1.updateViewPort. This will trigger drawChart. Assuming the DrawFibnodes is inside drawChart, it will draw the fib nodes.

Hope this can help.

Regards
Peter Kwan

  Re: How to synchronize DrawArea drawing with ChartViewer viewPort
Posted by Jianhua on Mar-28-2019 17:08
Hi Peter,
Thanks a lot for your help! I'm doing just what you told me. Your idea is great, and practical. I'm working on it now. If there's any other question, I'll ask you again. Thanks again!
Regards,
Jianhua

  Re: How to synchronize DrawArea drawing with ChartViewer viewPort
Posted by Jianhua on Mar-28-2019 20:12
Hi Peter,
My problem solved after using your ideas and sample code. Really appreciate!
Now I am working on  printing out the chart as a PDF or PNG file, do you have any suggestions how could I do this?  I wanted to print out the finance chart include the custom fibnodes drawing.
I hope to hear from you soon.
Regards,
Jianhua

  Re: How to synchronize DrawArea drawing with ChartViewer viewPort
Posted by Jianhua on Mar-28-2019 22:20
Hi Peter,
I found the solution to print the chart as PNG format. Thanks for your help again.

Regards,
Jianhua