Chart, showing date/time with mouse over - c#

I am currently attempting to show the x,y values whenever I mouse over a point on the chart but for the x axis is in a date/time format, and I want to display the date/time instead of the actual pixel value.
What I am currently using is this following code for the mouse over event
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
var pos = e.Location;
if (prevPosition.HasValue && pos == prevPosition.Value)
return;
tooltip.RemoveAll();
prevPosition = pos;
var results = chart1.HitTest(pos.X, pos.Y, false,
ChartElementType.DataPoint);
foreach (var result in results)
{
if (result.ChartElementType == ChartElementType.DataPoint)
{
var prop = result.Object as DataPoint;
if (prop != null)
{
var pointXPixel = result.ChartArea.AxisX.ValueToPixelPosition(prop.XValue);
var pointYPixel = result.ChartArea.AxisY.ValueToPixelPosition(prop.YValues[0]);
// check if the cursor is really close to the point (2 pixels around the point)
if (Math.Abs(pos.X - pointXPixel) < 2 &&
Math.Abs(pos.Y - pointYPixel) < 2)
{
tooltip.Show("X=" + prop.XValue + ", Y=" + prop.YValues[0], this.chart1,
pos.X, pos.Y - 15);
}
}
}
}
}
In terms of the formatting of the x axis goes, I have this
chart1.ChartAreas["ChartArea1"].AxisX.LabelStyle.Format = "MMM.dd.yyyy HH:mm:ss";
chart1.Series["Series1"].XValueType = ChartValueType.DateTime;
I was wondering if there was a simple way to convert the point into a date/time value.
Thank you

Related

TeeChart: Expand the "clickable" width of a Line/FastLine

I have a WinForms application where a number of lines are drawn in a TeeChart component. It is requested that it shall be possible to delete a line by right-clicking it.
Everything works fine, the clickseries event is captured and so on, but the user finds it difficult to hit the line on right click. The question is, is it possible to increase the region where the Line/FastLine object is sensible for clicking? That is, make the line wider without drawing the line any wider on the screen.
Tnx in advance
Yes, this is possible. The key to achieve that is PointInLineTolerance method. To achieve what you request you can combine it with NearestPoint's tool GetNearestPoint method as shown in this example:
public Form1()
{
InitializeComponent();
InitializeChart();
}
private void InitializeChart()
{
tChart1.Aspect.View3D = false;
tChart1.Series.Add(new Steema.TeeChart.Styles.Line()).FillSampleValues();
tChart1.MouseMove += TChart1_MouseMove;
}
private void TChart1_MouseMove(object sender, MouseEventArgs e)
{
var nearestPoint = new Steema.TeeChart.Tools.NearestPoint(tChart1[0]);
nearestPoint.Active = false;
var p = new Point(e.X, e.Y);
var index = nearestPoint.GetNearestPoint(p);
if (index != -1)
{
const int tolerance = 10;
var px = tChart1[0].CalcXPos(index);
var py = tChart1[0].CalcYPos(index);
var index2 = (index == tChart1[0].Count - 1) ? index - 1 : index + 1;
var qx = tChart1[0].CalcXPos(index2);
var qy = tChart1[0].CalcYPos(index2);
if (Steema.TeeChart.Drawing.Graphics3D.PointInLineTolerance(p, px, py, qx, qy, tolerance))
{
tChart1.Header.Text = "point " + index.ToString() + " clicked";
}
else
{
tChart1.Header.Text = "No point";
}
}
An alternative could be using an invisible fake series with same data as the original series.

WinForms: ToolTips will not (re)appear after the initial mouse hover

I am working on a form that uses a SharpMap MapBox to display objects as points on a world map. Currently, if I enter the MapBox (mapBox1) with the cursor and stop on the point, it displays the tooltip as I want it to. However, once I've stopped the mouse within the MapBox (not necessarily on the point) and move the mouse within the MapBox, moving to the point will not (re)display the tooltip. However, if I leave the MapBox (say, moving the cursor out of the window or onto one of the menu strips, or onto a button overlaid on the map) I can then get the tooltip to appear, but only once before I have to move the cursor as before.
What is causing this behaviour, and is there any easy way to fix it?
I've tried using ToolTip.Hide(), ToolTip.Active = false (and then setting it to true again when I want it displayed) and refreshing the MapBox at various points.
Relevant code:
The ToolTip is global, and the constructor defines it as follows:
toolTip.InitialDelay = 1000;
toolTip.ReshowDelay = 750;
toolTip.ShowAlways = true;
I then have two event handlers for the mouse, both tied to the MapBox. "obj" is a global object of a custom class containing the latitude and longitude points.
private void mapBox1_MouseHover(object sender, EventArgs e)
{
PointF pos = mapBox1.PointToClient(Cursor.Position);
int screenToleranceX = 20, screenToleranceY = 20;
PointF posLow = new PointF(pos.X - screenToleranceX, pos.Y - screenToleranceY);
PointF posHigh = new PointF(pos.X + screenToleranceX, pos.Y + screenToleranceY);
GeoAPI.Geometries.Coordinate objLoc = new GeoAPI.Geometries.Coordinate(obj.longitude, obj.latitude);
PointF objPoint = mapBox1.Map.WorldToImage(objLoc);
if (posLow.X <= objPoint.X && objPoint.X <= posHigh.X && posLow.Y <= objPoint.Y && objPoint.Y <= posHigh.Y)
{
toolTip.Active = true;
toolTip.Show(obj.Name, mapBox1, mapBox1.PointToClient(Cursor.Position));
}
}
private void mapBox1_MouseMove(GeoAPI.Geometries.Coordinate worldPos, MouseEventArgs imagePos)
{
PointF pos = mapBox1.PointToClient(Cursor.Position);
int screenToleranceX = 20, screenToleranceY = 20;
PointF posLow = new PointF(pos.X - screenToleranceX, pos.Y - screenToleranceY);
PointF posHigh = new PointF(pos.X + screenToleranceX, pos.Y + screenToleranceY);
GeoAPI.Geometries.Coordinate objLoc = new GeoAPI.Geometries.Coordinate(obj.longitude, obj.latitude);
PointF objPoint = mapBox1.Map.WorldToImage(objLoc);
if (toolTip.Active && (posLow.X > objPoint.X || objPoint.X > posHigh.X || posLow.Y > objPoint.Y || objPoint.Y > posHigh.Y))
{
toolTip.Active = false;
}
}
** EDIT **
As per the accepted answer, I have the following code as a solution, with hopes to refine it further as needed. This works for now, however (using an externally declared bool, toolTipDisp, defaulted to false):
private void mapBox1_MouseMove(GeoAPI.Geometries.Coordinate worldPos, MouseEventArgs imagePos)
{
PointF pos = mapBox1.PointToClient(Cursor.Position);
int screenToleranceX = 20, screenToleranceY = 20;
PointF posLow = new PointF(pos.X - screenToleranceX, pos.Y - screenToleranceY);
PointF posHigh = new PointF(pos.X + screenToleranceX, pos.Y + screenToleranceY);
GeoAPI.Geometries.Coordinate objLoc = new GeoAPI.Geometries.Coordinate(obj.longitude, obj.latitude);
PointF objPoint = mapBox1.Map.WorldToImage(objLoc);
if (posLow.X <= objPoint.X && objPoint.X <= posHigh.X && posLow.Y <= objPoint.Y && objPoint.Y <= posHigh.Y)
{
if (!toolTipDisp)
{
toolTip.Show(obj.Name, mapBox1, mapBox1.PointToClient(Cursor.Position));
toolTipDisp = true;
}
}
else
{
toolTip.Hide(mapBox1);
toolTipDisp = false;
}
}
Try this (pseudo-code):
private string _previous;
private void mapBox1_MouseMove(GeoAPI.Geometries.Coordinate worldPos, MouseEventArgs imagePos)
{
var text = ...; // generate tooltip text based on the new position
if(text != _previous)
{
_previous = text;
tooltip.Show(text, mapBox1, mapBox1.PointToClient(imagePos.Location));
}
}
private void mapBox1_MouseLeave(object sender, EventArgs e)
{
toolTip.Hide(mapBox1);
}

Kinect SDK: Skeleton flickering

I have a problem with this code.
When I use MoveTo, my skeleton flicks through the screen. I have made some little changes to the original code (here):
lock skeleton position to a specific Z position
increase horizontal speed (X)
I use XNA 4.0 and I call that member into Draw "callback".
So, the question is: why does the skeleton flick?
private Skeleton MoveTo2(Skeleton skToBeMoved) {
Joint newJoint = new Joint();
///Based on the HipCenter
float howMuchMoveToX = ((skToBeMoved.Joints[JointType.HipCenter].Position.X - settings_skel_offset_x) * -1) * settings_skel_offset_x_mult;
float howMuchMoveToY = (skToBeMoved.Joints[JointType.HipCenter].Position.Y - settings_skel_offset_y) * -1;
float howMuchMoveToZ = (skToBeMoved.Joints[JointType.HipCenter].Position.Z - settings_skel_offset_z) * -1;
foreach (JointType item in Enum.GetValues(typeof(JointType)))
{
newJoint = skToBeMoved.Joints[item];
SkeletonPoint pos = new SkeletonPoint()
{
X = (float)(newJoint.Position.X + (howMuchMoveToX)),
Y = (float)(newJoint.Position.Y + (howMuchMoveToY)),
Z = (float)(newJoint.Position.Z + (howMuchMoveToZ)),
};
if (XnaBasics.settings_skel_lock_z)
{
pos.Z = settings_skel_offset_z;
}
newJoint.Position = pos;
Debug.WriteLine("SkelID: "+skToBeMoved.TrackingId+ " howMuchMoveToX: " + howMuchMoveToX + " oldPosX: " + skToBeMoved.Joints[item].Position.X + " newPosX: " + newJoint.Position.X);
skToBeMoved.Joints[item] = newJoint;
}
return skToBeMoved;
}
SOLVED
I put the member call into "Update" callback, before it was called from the "Draw" callback.
Correct Code (relevant part)
public override void Update(GameTime gameTime)
{
// Debug.WriteLine("= UPDATE - SkeletonStreamRender");
if (null == this.Chooser.Sensor || false == this.Chooser.Sensor.IsRunning || KinectStatus.Connected != this.Chooser.Sensor.Status)
{
return;
}
if (skeletonDrawn || !drawChk)
{
using (var skeletonFrame = this.Chooser.Sensor.SkeletonStream.OpenNextFrame(0))
{
if (null == skeletonData || skeletonData.Length != skeletonFrame.SkeletonArrayLength)
{
skeletonData = new Skeleton[skeletonFrame.SkeletonArrayLength];
}
skeletonFrame.CopySkeletonDataTo(skeletonData);
int counter = 0;
foreach (Skeleton s in skeletonData)
{
if (s.TrackingState == SkeletonTrackingState.Tracked)
{
playersID = s.TrackingId;
Skeleton skeleton = MoveTo2(s);
skeletonData[counter] = skeleton;
continue;
}
counter++;
}
skeletonDrawn = false;
}
[CUT]
Wrong call from Draw
public override void Draw(GameTime gameTime)
{
// Debug.WriteLine("== DRAW - SkeletonStreamRender");
// If the joint texture isn't loaded, load it now
if (null == this.jointTexture)
{
this.LoadContent();
}
// If we don't have data, lets leave
if (null == skeletonData || null == this.mapMethod)
{
return;
}
if (false == this.initialized)
{
this.Initialize();
}
this.SharedSpriteBatch.Begin();
foreach (var skeleton in skeletonData)
{
if (playersID != skeleton.TrackingId)
continue;
switch (skeleton.TrackingState)
{
case SkeletonTrackingState.NotTracked:
// non tracciato
break;
case SkeletonTrackingState.Tracked:
// blocco la posizione Z
Skeleton skeleton = MoveTo2(skeletonTmp);
// Draw Bones
this.DrawBone(skeleton.Joints, JointType.Head, JointType.ShoulderCenter);
this.DrawBone(skeleton.Joints, JointType.ShoulderCenter, JointType.ShoulderLeft);
this.DrawBone(skeleton.Joints, JointType.ShoulderCenter, JointType.ShoulderRight);
this.DrawBone(skeleton.Joints, JointType.ShoulderCenter, JointType.Spine);
[CUT]

see values of chart points when the mouse is on points

I have a chart and I want the user to see the values when the pointer is on the points.
By using digEmAll's help in the page finding the value of the points in a chart ,I could write the following code:
Point? prevPosition = null;
ToolTip tooltip = new ToolTip();
void chart1_MouseMove(object sender, MouseEventArgs e)
{
var pos = e.Location;
if (prevPosition.HasValue && pos == prevPosition.Value)
return;
tooltip.RemoveAll();
prevPosition = pos;
var results = chart1.HitTest(pos.X, pos.Y, false, ChartElementType.PlottingArea);
foreach (var result in results)
{
if (result.ChartElementType == ChartElementType.PlottingArea)
{
chart1.Series[0].ToolTip = "X=#VALX, Y=#VALY";
}
}
}
by the above code,the user can see the values when the pointer is near to a series.But now How can I let the user to see the values only when the pointer is on the points?
I replaced
int k = result.PointIndex;
if (k >= 0)
{
chart1.Series[0].Points[k].ToolTip = "X=#VALX, Y=#VALY";
}
instead of
chart1.Series[0].ToolTip = "X=#VALX, Y=#VALY";
to solve my problem.But It wasn't usefull.
You should modify the code in this way:
Point? prevPosition = null;
ToolTip tooltip = new ToolTip();
void chart1_MouseMove(object sender, MouseEventArgs e)
{
var pos = e.Location;
if (prevPosition.HasValue && pos == prevPosition.Value)
return;
tooltip.RemoveAll();
prevPosition = pos;
var results = chart1.HitTest(pos.X, pos.Y, false,
ChartElementType.DataPoint);
foreach (var result in results)
{
if (result.ChartElementType == ChartElementType.DataPoint)
{
var prop = result.Object as DataPoint;
if (prop != null)
{
var pointXPixel = result.ChartArea.AxisX.ValueToPixelPosition(prop.XValue);
var pointYPixel = result.ChartArea.AxisY.ValueToPixelPosition(prop.YValues[0]);
// check if the cursor is really close to the point (2 pixels around the point)
if (Math.Abs(pos.X - pointXPixel) < 2 &&
Math.Abs(pos.Y - pointYPixel) < 2)
{
tooltip.Show("X=" + prop.XValue + ", Y=" + prop.YValues[0], this.chart1,
pos.X, pos.Y - 15);
}
}
}
}
}
The idea is to check if the mouse is very close to the point e.g. 2 pixels around it (because is really unlikely to be exactly on the point) and show the tooltip in that case.
Here's a complete working example.
I would take this solution:
Add custom tooltip event handler:
this.chart1.GetToolTipText += this.chart1_GetToolTipText;
Implement event handler:
private void chart1_GetToolTipText(object sender, ToolTipEventArgs e)
{
// Check selected chart element and set tooltip text for it
switch (e.HitTestResult.ChartElementType)
{
case ChartElementType.DataPoint:
var dataPoint = e.HitTestResult.Series.Points[e.HitTestResult.PointIndex];
e.Text = string.Format("X:\t{0}\nY:\t{1}", dataPoint.XValue, dataPoint.YValues[0]);
break;
}
}
Consider the following as a possible better option than tooltips...use the label feature of the chart control.
DataPoint _prevPoint;
void chart1_MouseMove(object sender, MouseEventArgs e)
{
// this if statement clears the values from the previously activated point.
if (_prevPoint) {
_prevPoint.MarkerStyle = MarkerStyle.None;
_prevPoint.IsValueShownAsLabel = false;
}
var result = chart1.HitTest(e.X, e.Y, ChartElementType.DataPoint);
if (result.ChartElementType == ChartElementType.DataPoint)
{
var prop = result.Object as DataPoint;
if (prop != null)
{
prop.IsValueShownAsLabel = true;
prop.MarkerStyle = MarkerStyle.Star4;
}
}
}
I've tested this and i'm using it currently. It's very nice on charts with a lot of points since it shows the marker on the chart as well.

finding the value of the points in a chart

I have made a chart on my form.
I want the user to see the value, x_value and y_value of each part in a balloon by clicking on that part.
The ballon shoud disappear when the user moves the mouse.
How can I do that?
You could do something like this:
ToolTip tooltip = new ToolTip();
Point? clickPosition = null;
void chart1_MouseMove(object sender, MouseEventArgs e)
{
if (clickPosition.HasValue && e.Location != clickPosition)
{
tooltip.RemoveAll();
clickPosition = null;
}
}
void chart1_MouseClick(object sender, MouseEventArgs e)
{
var pos = e.Location;
clickPosition = pos;
var results = chart1.HitTest(pos.X, pos.Y, false,
ChartElementType.PlottingArea);
foreach (var result in results)
{
if (result.ChartElementType == ChartElementType.PlottingArea)
{
var xVal = result.ChartArea.AxisX.PixelPositionToValue(pos.X);
var yVal = result.ChartArea.AxisY.PixelPositionToValue(pos.Y);
tooltip.Show("X=" + xVal + ", Y=" + yVal,
this.chart1, e.Location.X,e.Location.Y - 15);
}
}
}
Result:
EDIT :
to show the tooltip whenever the mouse move, you can use the following code:
Point? prevPosition = null;
ToolTip tooltip = new ToolTip();
void chart1_MouseMove(object sender, MouseEventArgs e)
{
var pos = e.Location;
if (prevPosition.HasValue && pos == prevPosition.Value)
return;
tooltip.RemoveAll();
prevPosition = pos;
var results = chart1.HitTest(pos.X, pos.Y, false,
ChartElementType.PlottingArea);
foreach (var result in results)
{
if (result.ChartElementType == ChartElementType.PlottingArea)
{
var xVal = result.ChartArea.AxisX.PixelPositionToValue(pos.X);
var yVal = result.ChartArea.AxisY.PixelPositionToValue(pos.Y);
tooltip.Show("X=" + xVal + ", Y=" + yVal, this.chart1,
pos.X, pos.Y - 15);
}
}
}
Note that this shows the tooltip on any position of the chart. If you want to show it only when the mouse is near to a series point, you can use a mschart functionality e.g. :
yourSeries.ToolTip = "X=#VALX, Y=#VALY";
(further examples here)

Categories

Resources