菜鸡一个,不喜勿喷~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~纯属记录
有大佬提供更好的解决思路不胜感激。
最近在使用MSChart控件做数据显示项目,领导要求要像股票软件,跟随鼠标移动显示数据。
查阅大量CSDN文档加自己调试[狗头][狗头][狗头]
PS:还要求动画 还未实现
思路:
1、根据鼠标位置获取对应在chart控件X轴位置 --使用MouseMover事件
2、在点击位置,画个label 当交叉线 label的高度和y轴坐标需要转换
3、遍历判断该位置在哪两个数据点中间,将label"磁吸"过去,取左边点(待优化)
4、显示tooltip
(别喷我啊,喷我就哭给你看)
private int _CurrentXValue = 0;//记录当前鼠标x轴位置
private void chtDemand_MouseMove(object sender, MouseEventArgs e)
{
HitTestResult myTestResult = chtDemand.HitTest(e.X, e.Y);
if (myTestResult.ChartElementType == ChartElementType.DataPoint || myTestResult.ChartElementType == ChartElementType.PlottingArea ||
myTestResult.ChartElementType == ChartElementType.Gridlines)
{
if(_CurrentXValue == e.X)//鼠标没移动就不刷了
{
return;
}
_CurrentXValue = e.X;
ChartArea chartArea = chtDemand.ChartAreas[0];
lblLineH.Visible = true;
int dstart = (int)chartArea.AxisY.ValueToPixelPosition(chtDemand.ChartAreas[0].AxisY.Maximum);
int dend = (int)chartArea.AxisY.ValueToPixelPosition(chtDemand.ChartAreas[0].AxisY.Minimum);
lblLineH.Height = dend - dstart;//高度=Y轴高度
lblLineH.Width = 1;
lblLineH.Location = new Point(e.X, dstart);
//鼠标坐标转换成chart坐标
double xValue = chartArea.AxisX.PixelPositionToValue(e.X);
for (int i = 0; i < chtDemand.Series[0].Points.Count - 1; i++)
{
if (chtDemand.Series[0].Points[i].XValue <= xValue && xValue <= chtDemand.Series[0].Points[i + 1].XValue)
{
DataPoint p1 = chtDemand.Series[0].Points[i];
DataPoint p2 = chtDemand.Series[1].Points[i];
DataPoint p3 = chtDemand.Series[2].Points[i];
DataPoint p4 = chtDemand.Series[3].Points[i];
DateTime pointDateTime = DateTime.FromOADate(p1.XValue);
string str = string.Format("发生时间:{0}\r\n正向有功总需量(kW):{1}\r\nA相正向有功总需量(kW):{2}\r\nB相正向有功总需量(kW):{3}\r\nC相正向有功总需量(kW):{4}"
, pointDateTime.ToString("HH:mm:ss"), p1.YValues[0], p2.YValues[0], p3.YValues[0], p4.YValues[0]);
toolTip1.Active = true;//form里拖个tooltip
toolTip1.Show(str, chtDemand, e.X, e.Y);
}
}
}
else
{
lblLineH.Visible = false;
toolTip1.Active = false;
}
}
心得:静下来心来思考才是解决问题的最佳途径
~~~~~~~~~~~~~~~~~优化分割线
优化了下
for循环的作用应该就是确定是 为哪个数据点
磁吸数据点也优化为更靠近哪一边的
如果为正确数据点 tooltip就显示,如果不是就不显示
private void chtDemand_MouseMove(object sender, MouseEventArgs e)
{
HitTestResult myTestResult = chtDemand.HitTest(e.X, e.Y);
if (myTestResult.ChartElementType == ChartElementType.DataPoint || myTestResult.ChartElementType == ChartElementType.PlottingArea ||
myTestResult.ChartElementType == ChartElementType.Gridlines)
{
if(_CurrentXValue == e.X)
{
return;
}
_CurrentXValue = e.X;
ChartArea chartArea = chtDemand.ChartAreas[0];
if (chtDemand.Series[0].Points.Count < 1)
{
lblLineH.Visible = false;
}
else
{
lblLineH.Visible = true;
}
int dstart = (int)chartArea.AxisY.ValueToPixelPosition(chtDemand.ChartAreas[0].AxisY.Maximum);
int dend = (int)chartArea.AxisY.ValueToPixelPosition(chtDemand.ChartAreas[0].AxisY.Minimum);
lblLineH.Height = dend - dstart;
lblLineH.Width = 1;
lblLineH.Location = new Point(e.X, dstart);
//鼠标坐标转换成chart坐标
double xValue = chartArea.AxisX.PixelPositionToValue(e.X);
int index = 9999;
for (int i = 0; i < chtDemand.Series[1].Points.Count - 1; i++)//已曲线1为主 曲线0被添加了 23:59:59 占位
{
DataPoint last = chtDemand.Series[0].Points[i];
DataPoint next = chtDemand.Series[0].Points[i + 1];
//DateTime lastPointDateTime = DateTime.FromOADate(last.XValue);
//double error = (lastPointDateTime.AddMinutes(1)).ToOADate() - lastPointDateTime.ToOADate();//误差为1分钟内
//可以判断是否在某点的左右1分钟范围 修改下面的if就可以
if (last.XValue <= xValue && xValue <= next.XValue)//确定在哪两个点中间
{
double split = (last.XValue + next.XValue) / 2;
if (split <= xValue)
{
index = i + 1;
}
else
{
index = i;
}
}
}
if(index != 9999)
{
DataPoint p1 = chtDemand.Series[0].Points[index];
DataPoint p2 = chtDemand.Series[1].Points[index];
DataPoint p3 = chtDemand.Series[2].Points[index];
DataPoint p4 = chtDemand.Series[3].Points[index];
DateTime pointDateTime = DateTime.FromOADate(p1.XValue);
string str = string.Format("发生时间:{0}\r\n总功率因数:{1}\r\nA相功率因数:{2}\r\nB相功率因数:{3}\r\nC相功率因数:{4}"
, pointDateTime.ToString("HH:mm:ss"), p1.YValues[0], p2.YValues[0], p3.YValues[0], p4.YValues[0]);
toolTip1.Active = true;
toolTip1.Show(str, chtDemand, e.X, e.Y);
}
else
{
toolTip1.Active = false;
}
}
else
{
lblLineH.Visible = false;
toolTip1.Active = false;
}
}