451 lines
18 KiB
C#
451 lines
18 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.Drawing;
|
||
using System.Data;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Windows.Forms;
|
||
|
||
using System.Windows.Forms.DataVisualization.Charting;
|
||
using System.Collections;
|
||
|
||
namespace chartTC
|
||
{
|
||
public delegate void clickEventHandler(Stack name, Stack x, Stack y);
|
||
|
||
public partial class chartTC: UserControl
|
||
{
|
||
public chartTC()
|
||
{
|
||
InitializeComponent();
|
||
}
|
||
|
||
private void chart1_Click(object sender, EventArgs e)
|
||
{
|
||
|
||
}
|
||
|
||
private void chartTC_Load(object sender, EventArgs e)
|
||
{
|
||
chart1.Series.Clear();
|
||
//ChartHelper.AddSeries(chart1, "曲线图", SeriesChartType.Line, Color.Red, Color.Red);
|
||
//ChartHelper.SetTitle(chart1, "sif", new Font("微软雅黑", 12), Docking.Bottom, Color.White);
|
||
ChartHelper.SetStyle(chart1, Color.Transparent, Color.White);
|
||
//ChartHelper.SetLegend(chart1, Docking.Top, StringAlignment.Center, Color.Transparent, Color.White);
|
||
//ChartHelper.SetXY(chart1, "波长", "值", StringAlignment.Far, Color.Black, Color.Black, AxisArrowStyle.None/*AxisArrowStyle.SharpTriangle*/, 10, 5);
|
||
ChartHelper.SetMajorGrid(chart1, Color.Gray, 20, 2);
|
||
|
||
|
||
//chart1.GetToolTipText += new EventHandler<ToolTipEventArgs>(chart_GetToolTipText);//https://bbs.csdn.net/topics/390754014
|
||
|
||
|
||
chart1.ChartAreas[0].CursorX.Interval = 0;
|
||
chart1.ChartAreas[0].CursorX.IsUserEnabled = true;
|
||
chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
|
||
}
|
||
|
||
void chart_GetToolTipText(object sender, ToolTipEventArgs e)
|
||
{
|
||
if (e.HitTestResult.ChartElementType == ChartElementType.DataPoint)
|
||
{
|
||
int i = e.HitTestResult.PointIndex;
|
||
DataPoint dp = e.HitTestResult.Series.Points[i];
|
||
e.Text = string.Format("{1:F3}", dp.XValue, dp.YValues[0]);
|
||
}
|
||
}
|
||
|
||
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);
|
||
|
||
//double XVuale = chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X);
|
||
|
||
//chart1.Series[0].
|
||
|
||
//tooltip.Show("X=" + prop.AxisLabel + ", Y=" + prop.YValues[0], this.chart1, pos.X, pos.Y - 15);
|
||
|
||
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);
|
||
//}
|
||
|
||
tooltip.Show("X=" + prop.AxisLabel + ", Y=" + prop.YValues[0], this.chart1, pos.X, pos.Y - 15);
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void chart_MouseMove(object sender, MouseEventArgs e)
|
||
{
|
||
//labX.Text = e.X.ToString();
|
||
//labY.Text = e.Y.ToString();
|
||
|
||
//if (e.HitTestResult.ChartElementType == ChartElementType.DataPoint)
|
||
//{
|
||
// int i = e.HitTestResult.PointIndex;
|
||
// DataPoint dp = e.HitTestResult.Series.Points[i];
|
||
// e.Text = string.Format("{1:F3}", dp.XValue, dp.YValues[0]);
|
||
//}
|
||
|
||
|
||
//ChartHitInfo hitInfo = chartControl4.CalcHitInfo(e.Location);
|
||
//if (hitInfo.SeriesPoint != null)
|
||
//{
|
||
// MessageBox.Show(hitInfo.SeriesPoint.Values[0].ToString());
|
||
//}
|
||
}
|
||
|
||
private void chart_Wave1_MouseMove(object sender, MouseEventArgs e)
|
||
{
|
||
HitTestResult myTestResult = chart1.HitTest(e.X, e.Y);
|
||
if (myTestResult.ChartElementType == ChartElementType.DataPoint)
|
||
{
|
||
this.Cursor = Cursors.Cross;
|
||
int i = myTestResult.PointIndex;
|
||
DataPoint dp = myTestResult.Series.Points[i];
|
||
|
||
double doubleXValue = (dp.XValue);
|
||
double doubleYValue = dp.YValues[0];
|
||
//自我实现值的显示
|
||
MessageBox.Show(doubleYValue.ToString());
|
||
}
|
||
else
|
||
{
|
||
this.Cursor = Cursors.Default;
|
||
}
|
||
}
|
||
|
||
|
||
public event clickEventHandler clickPointEvent;
|
||
private void chart1_MouseClick(object sender, MouseEventArgs e)
|
||
{
|
||
if (chart1.Series.Count == 0)
|
||
return;
|
||
|
||
|
||
if (e.Button == MouseButtons.Left)
|
||
{
|
||
//var collection = chart1.Series.Select(series => series.Points.Where(point => point.XValue == 0).ToList()).ToList();//????????????????????????????????????????????????????????
|
||
//chart1.Series.ElementAt
|
||
|
||
|
||
|
||
////方式1:遍历x坐标处的所有y坐标
|
||
//var pos = e.Location;
|
||
|
||
//var yAxis = chart1.ChartAreas[0].AxisY;
|
||
//int yMin = (int)yAxis.ValueToPixelPosition(yAxis.Maximum) - 1;
|
||
//int yMax = (int)yAxis.ValueToPixelPosition(yAxis.Minimum);
|
||
|
||
//for (int i = yMin; i < yMax + 1; i++)
|
||
//{
|
||
// var results = chart1.HitTest(pos.X, pos.Y, true, 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]);
|
||
|
||
// int b = 1;
|
||
// }
|
||
// }
|
||
// }
|
||
//}
|
||
|
||
|
||
|
||
//方式2:
|
||
double cursorPos = chart1.ChartAreas[0].CursorX.Position;
|
||
|
||
var xAxis = chart1.ChartAreas[0].AxisX;
|
||
|
||
double XVuale1 = chart1.ChartAreas[0].AxisX.ValueToPixelPosition(e.X);
|
||
double XVuale2 = chart1.ChartAreas[0].AxisX.GetPosition(e.X);
|
||
|
||
double XVuale3 = Math.Round(chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X));
|
||
|
||
if (XVuale3-1 < xAxis.Minimum)//XVuale3-1:因为在chart上绘制的曲线的第一个点的x坐标为1而不是0;
|
||
XVuale3 = 1;
|
||
else if (chart1.Series[0].Points.Count - 1 < XVuale3 - 1)
|
||
XVuale3= chart1.Series[0].Points.Count;
|
||
|
||
chart1.ChartAreas[0].CursorX.Position = XVuale3;
|
||
|
||
Stack name = new Stack();
|
||
Stack x = new Stack();
|
||
Stack y = new Stack();
|
||
for (int i = 0; i < chart1.Series.Count; i++)
|
||
{
|
||
DataPoint p1 = chart1.Series[i].Points.ElementAt((int)XVuale3 - 1);
|
||
|
||
name.Push(chart1.Series[i].Name);
|
||
x.Push(p1.AxisLabel);
|
||
y.Push(p1.YValues[0]);
|
||
}
|
||
|
||
if(clickPointEvent != null)
|
||
clickPointEvent(name, x, y);
|
||
}
|
||
else if (e.Button == MouseButtons.Right)
|
||
{
|
||
contextMenuStrip1.Show(chart1, e.X, e.Y);
|
||
}
|
||
|
||
}
|
||
|
||
private double calcCursorGraphX(int clientX)
|
||
{
|
||
var xAxis = chart1.ChartAreas[0].AxisX;
|
||
int xRight = (int)xAxis.ValueToPixelPosition(xAxis.Maximum) - 1;
|
||
int xLeft = (int)xAxis.ValueToPixelPosition(xAxis.Minimum);
|
||
|
||
if (clientX > xRight)
|
||
{
|
||
return xAxis.Maximum;
|
||
}
|
||
else if (clientX < xLeft)
|
||
{
|
||
return xAxis.Minimum;
|
||
}
|
||
else
|
||
{
|
||
return xAxis.PixelPositionToValue(clientX);
|
||
}
|
||
}
|
||
|
||
//private int nearestPreceedingValue(double x)
|
||
//{
|
||
// var bpData = chart1.Series[0].Points;
|
||
// int bpIndex = bpData.BinarySearch(x, (xVal, point) => Math.Sign(x - point.XValue));
|
||
|
||
// if (bpIndex < 0)
|
||
// {
|
||
// bpIndex = ~bpIndex; // BinarySearch() returns the index of the next element LARGER than the target.
|
||
// bpIndex = Math.Max(0, bpIndex - 1); // We want the value of the previous element, so we must decrement the returned index.
|
||
// } // If this is before the start of the graph, use the first valid data point.
|
||
|
||
// return bpIndex;
|
||
//}
|
||
|
||
private void clearAllToolStripMenuItem_Click(object sender, EventArgs e)
|
||
{
|
||
chart1.Series.Clear();
|
||
}
|
||
|
||
public void clearAll()
|
||
{
|
||
chart1.Series.Clear();
|
||
}
|
||
|
||
private Color ss()
|
||
{
|
||
int iSeed = 10;
|
||
Random ro = new Random(10);
|
||
long tick = DateTime.Now.Ticks;
|
||
Random ran = new Random((int)(tick & 0xffffffffL) | (int)(tick >> 32));
|
||
|
||
int R = ran.Next(255);
|
||
int G = ran.Next(255);
|
||
int B = ran.Next(255);
|
||
B = (R + G > 400) ? R + G - 400 : B;//0 : 380 - R - G;
|
||
B = (B > 255) ? 255 : B;
|
||
return Color.FromArgb(R, G, B);
|
||
|
||
|
||
|
||
//return or.FromArgb(random.Next(255), random.Next(255), random.Next(255));
|
||
}
|
||
|
||
public Color GetRandomColor()
|
||
{
|
||
Random RandomNum_First = new Random((int)DateTime.Now.Ticks);
|
||
// 对于C#的随机数,没什么好说的
|
||
System.Threading.Thread.Sleep(RandomNum_First.Next(50));
|
||
Random RandomNum_Sencond = new Random((int)DateTime.Now.Ticks);
|
||
|
||
// 为了在白色背景上显示,尽量生成深色
|
||
int int_Red = RandomNum_First.Next(256);
|
||
int int_Green = RandomNum_Sencond.Next(256);
|
||
int int_Blue = (int_Red + int_Green > 400) ? 0 : 400 - int_Red - int_Green;
|
||
int_Blue = (int_Blue > 255) ? 255 : int_Blue;
|
||
|
||
return Color.FromArgb(int_Red, int_Green, int_Blue);
|
||
}
|
||
|
||
public void addSeries(string[] x, double[] y,string name)
|
||
{
|
||
int count = chart1.Series.Count;
|
||
|
||
//ChartHelper.AddSeries(chart1, name, SeriesChartType.Line, Color.Green, Color.Red, false);
|
||
//ChartHelper.AddSeries(chart1, name, SeriesChartType.Line, ss(), ss(), false);
|
||
ChartHelper.AddSeries(chart1, name, SeriesChartType.Line, GetRandomColor(), GetRandomColor(), false);
|
||
|
||
chart1.Series[count].Points.DataBindXY(x, y);
|
||
//chart1.Series[count].Points.DataBindY(y);
|
||
}
|
||
|
||
private void chart1_MouseDoubleClick(object sender, MouseEventArgs e)
|
||
{
|
||
//Chart chart1 = sender as Chart;
|
||
//右键恢复事件
|
||
if (e.Button == MouseButtons.Left)
|
||
{
|
||
chart1.ChartAreas[0].AxisX.ScaleView.ZoomReset(0);
|
||
}
|
||
}
|
||
}
|
||
|
||
//https://blog.csdn.net/boxuming/article/details/89678159?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-4.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-4.pc_relevant_default&utm_relevant_index=9
|
||
public class ChartHelper
|
||
{
|
||
/// <summary>
|
||
/// Name:添加序列
|
||
/// Author:by boxuming 2019-04-28 13:59
|
||
/// </summary>
|
||
/// <param name="chart">图表对象</param>
|
||
/// <param name="seriesName">序列名称</param>
|
||
/// <param name="chartType">图表类型</param>
|
||
/// <param name="color">颜色</param>
|
||
/// <param name="markColor">标记点颜色</param>
|
||
/// <param name="showValue">是否显示数值</param>
|
||
public static void AddSeries(Chart chart, string seriesName, SeriesChartType chartType, Color color, Color markColor, bool showValue = false)
|
||
{
|
||
chart.Series.Add(seriesName);
|
||
chart.Series[seriesName].ChartType = chartType;
|
||
chart.Series[seriesName].Color = color;
|
||
|
||
if (showValue)
|
||
{
|
||
chart.Series[seriesName].IsValueShownAsLabel = true;
|
||
chart.Series[seriesName].MarkerStyle = MarkerStyle.Circle;
|
||
chart.Series[seriesName].MarkerColor = markColor;
|
||
chart.Series[seriesName].LabelForeColor = color;
|
||
chart.Series[seriesName].LabelAngle = -90;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Name:设置标题
|
||
/// Author:by boxuming 2019-04-28 14:25
|
||
/// </summary>
|
||
/// <param name="chart">图表对象</param>
|
||
/// <param name="chartName">图表名称</param>
|
||
public static void SetTitle(Chart chart, string chartName, Font font, Docking docking, Color foreColor)
|
||
{
|
||
chart.Titles.Add(chartName);
|
||
chart.Titles[0].Font = font;
|
||
chart.Titles[0].Docking = docking;
|
||
chart.Titles[0].ForeColor = foreColor;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Name:设置样式
|
||
/// Author:by boxuming 2019-04-23 14:04
|
||
/// </summary>
|
||
/// <param name="chart">图表对象</param>
|
||
/// <param name="backColor">背景颜色</param>
|
||
/// <param name="foreColor">字体颜色</param>
|
||
public static void SetStyle(Chart chart, Color backColor, Color foreColor)
|
||
{
|
||
chart.BackColor = backColor;
|
||
chart.ChartAreas[0].BackColor = backColor;
|
||
chart.ForeColor = Color.Red;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Name:设置图例
|
||
/// Author:by boxuming 2019-04-23 14:30
|
||
/// </summary>
|
||
/// <param name="chart">图表对象</param>
|
||
/// <param name="docking">停靠位置</param>
|
||
/// <param name="align">对齐方式</param>
|
||
/// <param name="backColor">背景颜色</param>
|
||
/// <param name="foreColor">字体颜色</param>
|
||
public static void SetLegend(Chart chart, Docking docking, StringAlignment align, Color backColor, Color foreColor)
|
||
{
|
||
chart.Legends[0].Docking = docking;
|
||
chart.Legends[0].Alignment = align;
|
||
chart.Legends[0].BackColor = backColor;
|
||
chart.Legends[0].ForeColor = foreColor;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Name:设置XY轴
|
||
/// Author:by boxuming 2019-04-23 14:35
|
||
/// </summary>
|
||
/// <param name="chart">图表对象</param>
|
||
/// <param name="xTitle">X轴标题</param>
|
||
/// <param name="yTitle">Y轴标题</param>
|
||
/// <param name="align">坐标轴标题对齐方式</param>
|
||
/// <param name="foreColor">坐标轴字体颜色</param>
|
||
/// <param name="lineColor">坐标轴颜色</param>
|
||
/// <param name="arrowStyle">坐标轴箭头样式</param>
|
||
/// <param name="xInterval">X轴的间距</param>
|
||
/// <param name="yInterval">Y轴的间距</param>
|
||
public static void SetXY(Chart chart, string xTitle, string yTitle, StringAlignment align, Color foreColor, Color lineColor, AxisArrowStyle arrowStyle, double xInterval, double yInterval)
|
||
{
|
||
chart.ChartAreas[0].AxisX.Title = xTitle;
|
||
chart.ChartAreas[0].AxisY.Title = yTitle;
|
||
chart.ChartAreas[0].AxisX.TitleAlignment = align;
|
||
chart.ChartAreas[0].AxisY.TitleAlignment = align;
|
||
chart.ChartAreas[0].AxisX.TitleForeColor = foreColor;
|
||
chart.ChartAreas[0].AxisY.TitleForeColor = foreColor;
|
||
chart.ChartAreas[0].AxisX.LabelStyle = new LabelStyle() { ForeColor = foreColor };
|
||
chart.ChartAreas[0].AxisY.LabelStyle = new LabelStyle() { ForeColor = foreColor };
|
||
chart.ChartAreas[0].AxisX.LineColor = lineColor;
|
||
chart.ChartAreas[0].AxisY.LineColor = lineColor;
|
||
chart.ChartAreas[0].AxisX.ArrowStyle = arrowStyle;
|
||
chart.ChartAreas[0].AxisY.ArrowStyle = arrowStyle;
|
||
//chart.ChartAreas[0].AxisX.Interval = xInterval;
|
||
//chart.ChartAreas[0].AxisY.Interval = yInterval;
|
||
chart.ChartAreas[0].AxisY.IsStartedFromZero = false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Name:设置网格
|
||
/// Author:by boxuming 2019-04-23 14:55
|
||
/// </summary>
|
||
/// <param name="chart">图表对象</param>
|
||
/// <param name="lineColor">网格线颜色</param>
|
||
/// <param name="xInterval">X轴网格的间距</param>
|
||
/// <param name="yInterval">Y轴网格的间距</param>
|
||
public static void SetMajorGrid(Chart chart, Color lineColor, double xInterval, double yInterval)
|
||
{
|
||
chart.ChartAreas[0].AxisX.MajorGrid.LineColor = lineColor;
|
||
chart.ChartAreas[0].AxisY.MajorGrid.LineColor = lineColor;
|
||
chart.ChartAreas[0].AxisX.MajorGrid.Interval = xInterval;
|
||
chart.ChartAreas[0].AxisY.MajorGrid.Interval = yInterval;
|
||
}
|
||
}
|
||
}
|