|
problem with reset range while programe running |
Posted by tyr2000 on Oct-22-2012 20:10 |
|
I use the FinanceChart in mfc. In the beginning, I set the full range of 1000 candle bars.
the viewwith I set 100 candle bars. then i scroll the chart. when the very left candle
shows,i down load more 1000 data from the net. i reset the data buffer and the full range.
after setting the full range ,i set the new ViewPortLeft to the 1001 candle bars. when i
handle OnViewPortChanged , i can get the correct viewportleft value at the first time after
resetting the full range,but when handling second OnViewPortChanged ,the viewportleft is
not correct. why?
pls
help |
Re: problem with reset range while programe running |
Posted by Peter Kwan on Oct-23-2012 03:26 |
|
Hi tyr2000,
Without running your exact code, it is hard to see the exact cause of the problem. However, in general, the ViewPortLeft can only changed due to the following reasons:
(a) User mouse actions, such asuser dragging on the chart when the mouse usage is set to "Scroll on Drag" or "Zoom In".
(b) Your own code changes the view port (eg. by call setViewPortLeft).
(c) The view port settings is inconsistent or invalid. For example, (viewPortLeft + viewPortWidth) should not never exceed 1. If some code calls setViewPortLeft to change viewPortLeft, it may temporarily cause the (viewPortLeft + viewPortWidth) to exceed 1. The ChartViewer will not immediately take any action, as it is expecting the code to subsequently call setViewPortWidth to fix the problem. However, if the problem is never fixed, ChartViewer will at some point needs to adjust the view port size to make it consistent.
So for your case, to trouble-shoot the problem, you may consider the followings:
- When your code calls setViewPortLeft, have it checked to see if the view port settings are valid ( viewPortLeft >= 0 and viewPortLeft + viewPortWidth <= 1) ?
- Please set break points only all code that can change the viewPortLeft or viewPortWidth (set the break points on setViewPortLeft and setViewPortWidth), or put some print statements there so that you can know when they are called. This can help to determine if it is your code that changes the view port. For example the followings are one way to cause the problem you see:
(i) The code changes the viewPortLeft and triggers the onViewPortChanged event.
(ii) In the onViewPortChanged event, the code modifies the scrollbar, or date/time picker or other controls that may need to synchronize with the view port.
(iii) Because the other controls are modified, they may fire their own "onChange" (or similar) events. Their event handlers may change the view port.
Hope this can help.
Regards
Peter Kwan |
Re: problem with reset range while programe running |
Posted by tyr2000 on Oct-23-2012 11:35 |
|
I wirte some trace statement in OnViewPortChanged.
I get these:
viewport范围0.719618,0.997396
viewport范围0.586806,0.864583
viewport范围0.461372,0.739149
viewport范围0.173177,0.450955
viewport范围0.011285,0.289063
viewport范围0.000000,0.277778
insert more data in front of buffer
reset viewport
reset leftviewport to 0.892825
viewport范围0.000000,0.030068
when i drage the chart from left to right. I get view port change message, when I handle
the message,if i find the left view port is zero. I insert more data in front of the buffer.then
reset the fullsize and the leftviewport. after setting these things, i get another view port
change message, when handle this message ,i print the new view port range, the left view
port is not the pre data I set before. why?
the problem comes by chance,when i drag the chart fast , it occurs.
thx for help |
Re: problem with reset range while programe running |
Posted by tyr2000 on Oct-23-2012 16:23 |
|
I find some thing new about this problem. It seems a bug.
I trace this void CChartViewer::OnPlotAreaMouseDrag(UINT /* nFlags */, CPoint point)
function as follow:
case Chart::MouseUsageScroll :
{
//
// Mouse is used for drag scrolling. Scroll and update the view port.
//
TRACE("before dragto portLeftVal %f\\r\\n",getViewPortLeft());
if (m_isDragScrolling || isDrag(m_scrollDirection, point))
{
m_isDragScrolling = true;
switch (m_scrollDirection)
{
case Chart::DirectionHorizontal:
::SetCursor(getNoMoveHorizCursor());
break;
case Chart::DirectionVertical:
::SetCursor(getNoMoveVertCursor());
break;
default :
::SetCursor(getNoMove2DCursor());
break;
}
if (dragTo(m_scrollDirection,
point.x - m_plotAreaMouseDownXPos, point.y -
m_plotAreaMouseDownYPos))
updateViewPort(true, false);
TRACE("after dragto portLeftVal %f\\r\\n",getViewPortLeft());
}
when I check the log, before step in to dragTo, I get the right value which I reset
before. but after stepping out of dragTo, the value changed ,but seems not right.
reset viewport
reset viewport to 0.892825
before dragto portLeftVal 0.892825
after dragto portLeftVal 0.000000
these are logs;
0.892825 this value is the position i want the chart to show. before dragto I get this
value,but after dragto it changed. even though I moved my mouse, but i think the new
value should be around 0.892825. but now these two value differs too much.
thx to anyone who helps |
Re: problem with reset range while programe running |
Posted by Peter Kwan on Oct-24-2012 02:16 |
|
Hi tyr2000,
Do you mean you are trying to change the viewPortLeft in the middle of a "drag to scroll" operation (before you release the mouse button)?
In a "drag to scroll" operation, the mouse drag will modify viewPortLeft. If you overwrite the viewPortLeft (eg. setViewPortLeft), then as the mouse continue to drag, it will overwrite the viewPortLeft again to the value as according to the "drag to scroll" operation. If the user drags left so that "drag to scroll" determines the viewPortLeft is 0, and the user continues to drag left, the "drag to scroll" will continue to determine that the viewPortLeft is 0.
In other words, your code can overwrite the viewPortLeft, but "drag to scroll" can overwrite the viewPortLeft too. So the final viewPortLeft value will depend on who overwrites the viewPortLeft last. The fact that your code modifies the viewPortLeft will not affect how "drag to scroll" modifies the viewPortLeft. So to properly modify viewPortLeft, it should be done when "drag to scroll" is not active.
For your application, instead of "modifying the view port left when it reaches 0", I suggest you to set up the view port to a value that reflects your data range. For example, if your data span 1000 days, and you want to show only the last 10 days of data, you can set the viewPortLeft to 0.99. You do not need to load all 1000 days of data at once. May be initially you can just load last 100 days of data. When the user drags to viewPortLeft = 0.90, you can start to load more data.
Hope this can help.
Regards
Peter Kwan |
Re: problem with reset range while programe running |
Posted by tyr2000 on Oct-24-2012 09:01 |
|
thank you for your suggestion. You do catch my point. I do try to change the viewPortLeft
in the middle of a "drag to scroll" operation. You suggest me to preset the total count of
the full range, it does helps in showing the history data. But if I want to show history data
and realtime data, the total count can't be determined before the chart shown. So in my
knowladge, I have to change the viewPortLeft while draging.
thank you again for your help. It did make me more clear. |
Re: problem with reset range while programe running |
Posted by tyr2000 on Oct-24-2012 15:29 |
|
In OnPlotAreaMouseDrag function,
case Chart::MouseUsageScroll :
{
//
// Mouse is used for drag scrolling. Scroll and update the view port.
//
TRACE("before dragto portLeftVal %f\\r\\n",getViewPortLeft());
TRACE("before dragto fullrange %f\\r\\n",getViewPortLeft());
if (m_isDragScrolling || isDrag(m_scrollDirection, point))
{
m_isDragScrolling = true;
switch (m_scrollDirection)
{
case Chart::DirectionHorizontal:
::SetCursor(getNoMoveHorizCursor());
break;
case Chart::DirectionVertical:
::SetCursor(getNoMoveVertCursor());
break;
default :
::SetCursor(getNoMove2DCursor());
break;
}
if (dragTo(m_scrollDirection,
point.x - m_plotAreaMouseDownXPos, point.y -
m_plotAreaMouseDownYPos))
updateViewPort(true, false);
TRACE("drag from %d to
%d\\r\\n",m_plotAreaMouseDownXPos,point.x);
TRACE("after dragto portLeftVal %f\\r\\n",getViewPortLeft());
}
}
I tracked the ViewPortLeft before dragTo called , ViewPortLeft is what i want ,but after
dragTo ViewPortLeft changed but the value is very strange. before i set viewPortLeft, I
alse reset the fullrange. but dragTo seems doesn't notice the fullrange changed. When
viewportLeft reached to zero, I get more data ,then insert to the front of buffer, then
reset fullrange and viewportleft. so I think dragTo should calculate the new viewPortLeft
according to the new fullrange and the mouse moveing offset. If I reset the the new
viewportLeft to the middle of the new range and I have a huge range, a small mouse
movement can't make dragTo fuction set the new viewPortLeft to 0 or around 0. This is
my opinion. Do I think wrong?
pls help. this makes me desperate. |
Re: problem with reset range while programe running |
Posted by Peter Kwan on Oct-25-2012 00:00 |
|
Hi tyr2000,
You can change the setViewPortLeft when the mouse is not dragging.
You mentioned that you need to support historical and realtime data. I assume you know what are your historical data, so you can set (or at least estimate) the view port size and position based on the historical data. You also have realtime data. You may design your code to that the realtime data are read only if the mouse is not dragging. In this way, you can update the viewPortLeft to reflect your realtime data. (If the realtime data keep coming in during mouse drag, you can put the realtime data in a buffer first. and "commit" the data only when the mouse is no longer dragging.)
For the mouse drag code in CChartViewer, the view port position is determined based on:
(a) The view port position when the mouse drag begins. See "ViewPortManager.startDrag".
http://www.advsofteng.com/doc/cdcpp.htm#ViewPortManager.startDrag.htm
(b) The distance that the mouse has travelled since the mouse drag begins. See "ViewPortManager.DragTo".
http://www.advsofteng.com/doc/cdcpp.htm#ViewPortManager.dragTo.htm
Note that the mouse drag code does not depend on changes to the view port during the drag. It is always computed based on "the view port position when the mouse drag begins" and the "the distance that the mouse has travelled since the mouse drag begins".
After some thinking, in your case, if you really want to change the view port when the mouse is still dragging, you may consider to "restart" the mouse drag by calling "startDrag" again and updating m_plotAreaMouseDownXPos and m_plotAreaMouseDownYPos.
Hope this can help.
Regards
Peter Kwan |
|