Reference documentation:
1. How to display time on the x-axis
The x-axis of c# chart sets the time format, the first coordinate starts from 0_c# chart coordinate axis-CSDN blog
2. Dynamic curve drawing (can be partially enlarged)
C# winform multiple charts dynamic curve drawing (can be partially enlarged)_winform curve chart-CSDN blog
3. When the amount of data is large, a scroll bar appears on the x-axis
Chart control in C#–(When the amount of data is large, a scroll bar appears on the x-axis)_winform chart x-axis millisecond scroll bar-CSDN Blog
4. Add border lines
c# chart control adds boundary value lines and scalability functions – AKA-Green – Blog Park (cnblogs.com)
Combined with the above reference, the x-axis is set to ms and the scroll bar can be dragged, supports zooming in and out, and supports maximum value display.
X axis type setting
//interval //chartArea.AxisY.Interval = 20; //chartArea.AxisY.Minimum = 0; //chartArea.AxisY.Maximum = 100; chartArea.AxisX.LabelStyle.Format = "yy-MM-dd\r\\ HH:mm:ss.fff"; //abscissa format chartArea.AxisX.IntervalType = DateTimeIntervalType.Milliseconds;//If it is time type data, the interval mode can be seconds, minutes, hours //chartArea.AxisX.Minimum = dateTime.ToOADate(); //chartArea.AxisX.Maximum = dateTime.AddMilliseconds(1000).ToOADate(); chartArea.AxisX.Interval = DateTime.Parse("00:00:00.100").Millisecond;
Pay special attention to the settings of the data view, otherwise the mouse will not be able to drag the scroll axis.
//Data view chartArea.AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All;//Enable the X-axis scroll bar button chartArea.AxisX.ScaleView.SizeType = DateTimeIntervalType.Auto; chartArea.AxisX.ScaleView.MinSize = 100; chartArea.AxisX.ScaleView.MinSizeType = DateTimeIntervalType.Milliseconds; chartArea.AxisX.ScaleView.SmallScrollMinSize = 100; chartArea.AxisX.ScaleView.SmallScrollMinSizeType = DateTimeIntervalType.Milliseconds; chartArea.AxisX.ScaleView.SmallScrollSize = 100; chartArea.AxisX.ScaleView.SmallScrollSizeType = DateTimeIntervalType.Milliseconds; chartArea.AxisX.ScaleView.Zoomable = true;
The type is set to ms. If the unit of the scroll axis is too large by default, the interface will display in ms and the scroll axis will not be dragged.
To realize the scroll bar following the curve in real time, you mainly need to set the value of chart1.ChartAreas[0].AxisX.ScaleView.Position.
The maximum number of data displayed on a page is determined by chart1.ChartAreas[0].AxisX.ScaleView.Size, combined with chartArea.AxisX.Interval = DateTime.Parse(“00:00:00.100”).Millisecond; set in the interval; The parameters can be used to calculate how many data a page can display.
range = r.Next(1, 60); //Randomly pick a number dateTime = dateTime.AddMilliseconds(100); series1.Points.AddXY(dateTime, 5 + range); //Set series points chart1.ChartAreas[0].AxisX.ScaleView.Size = dateTime.AddMilliseconds(900).ToOADate() - dateTime.ToOADate(); sum + + ; if (sum <= chart1.ChartAreas[0].AxisX.ScaleView.Size) chart1.ChartAreas[0].AxisX.ScaleView.Position = dateTime.ToOADate(); else chart1.ChartAreas[0].AxisX.ScaleView.Position = dateTime.ToOADate() - chart1.ChartAreas[0].AxisX.ScaleView.Size;
overall code
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting; using static System.Windows.Forms.VisualStyles.VisualStyleElement; using ToolTip = System.Windows.Forms.ToolTip; namespace TemperDisplay { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { createSeries(); CreateChart(); } private void CreateChart() { ChartArea chartArea = chart1.ChartAreas[0]; dateTime = DateTime.Now; //cursor chartArea.CursorX.IsUserEnabled = true; chartArea.CursorX.IsUserSelectionEnabled = true; chartArea.CursorX.AutoScroll = true; chartArea.CursorX.SelectionColor = Color.SkyBlue; chartArea.CursorX.IntervalType = DateTimeIntervalType.Milliseconds; chartArea.CursorX.Interval = 1; chartArea.CursorX.AxisType = AxisType.Primary; //Data view chartArea.AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All;//Enable the X-axis scroll bar button chartArea.AxisX.ScaleView.SizeType = DateTimeIntervalType.Auto; chartArea.AxisX.ScaleView.MinSize = 100; chartArea.AxisX.ScaleView.MinSizeType = DateTimeIntervalType.Milliseconds; chartArea.AxisX.ScaleView.SmallScrollMinSize = 100; chartArea.AxisX.ScaleView.SmallScrollMinSizeType = DateTimeIntervalType.Milliseconds; chartArea.AxisX.ScaleView.SmallScrollSize = 100; chartArea.AxisX.ScaleView.SmallScrollSizeType = DateTimeIntervalType.Milliseconds; chartArea.AxisX.ScaleView.Zoomable = true; //Exterior chartArea.BackColor = Color.AliceBlue; //Background color chartArea.BackSecondaryColor = Color.White; //Gradient background color chartArea.BackGradientStyle = GradientStyle.TopBottom; //Gradient mode chartArea.BackHatchStyle = ChartHatchStyle.None; //Background shadow chartArea.BorderDashStyle = ChartDashStyle.NotSet; //Border line style chartArea.BorderWidth = 1; //Border width chartArea.BorderColor = Color.Black; //Dividing line chartArea.AxisX.MajorGrid.Enabled = true; chartArea.AxisY.MajorGrid.Enabled = true; // Axis tag chartArea.AxisY.Title = @"Value"; chartArea.AxisY.LabelAutoFitMinFontSize = 5; chartArea.AxisX.Title = @"Time"; chartArea.AxisX.IsLabelAutoFit = true; chartArea.AxisX.LabelAutoFitMinFontSize = 5; chartArea.AxisX.LabelStyle.Angle = 0; //Label rotation angle -90 --- 90 chartArea.AxisX.LabelStyle.IsEndLabelVisible = true; chartArea.AxisX.TextOrientation = TextOrientation.Auto; //Text direction //interval //chartArea.AxisY.Interval = 20; //chartArea.AxisY.Minimum = 0; //chartArea.AxisY.Maximum = 100; chartArea.AxisX.LabelStyle.Format = "yy-MM-dd\r\\ HH:mm:ss.fff"; //abscissa format chartArea.AxisX.IntervalType = DateTimeIntervalType.Milliseconds;//If it is time type data, the interval mode can be seconds, minutes, hours //chartArea.AxisX.Minimum = dateTime.ToOADate(); //chartArea.AxisX.Maximum = dateTime.AddMilliseconds(1000).ToOADate(); chartArea.AxisX.Interval = DateTime.Parse("00:00:00.100").Millisecond; //Exterior chartArea.AxisY.LineWidth = 2; //Vertical edge width of data table chartArea.AxisY.LineColor = Color.Black; //Color of vertical edge of data table chartArea.AxisY.Enabled = AxisEnabled.True; chartArea.AxisX.LineWidth = 2; chartArea.AxisX.LineColor = Color.Black; chartArea.AxisX.Enabled = AxisEnabled.True; //Auxiliary lines double max = 25; StripLine stripMax = new StripLine(); stripMax.Text = string.Format("Maximum: {0:F}", max);//Display text stripMax.BackColor = Color.FromArgb(208, 109, 106);//Background color stripMax.Interval = 0;//interval stripMax.IntervalOffset = max;//Offset stripMax.StripWidth = 0.001;//Line width stripMax.ForeColor = Color.Yellow;//Foreground color stripMax.TextAlignment = StringAlignment.Near;//Text alignment chartArea.AxisY.StripLines.Add(stripMax);//Add to ChartAreas //Chart area rectangular position //chartArea.Position.Height = 85; //chartArea.Position.Width = 85; //chartArea.Position.X = 5; //chartArea.Position.Y = 7; //Gradient style chart1.BackGradientStyle = GradientStyle.TopBottom; //Chart border color, chart1.BorderlineColor = Color.FromArgb(26, 59, 105); //Chart border line style chart1.BorderlineDashStyle = ChartDashStyle.Solid; //The width of the chart border line chart1.BorderlineWidth = 2; //The skin of the chart border chart1.BorderSkin.SkinStyle = BorderSkinStyle.Emboss; } Series series1; private void createSeries() { //Series1 series1 = chart1.Series[0]; //Series1 style series1.ToolTip = "Temperature:#VALY{F1}\\ Time:#VALX{HH-mm-dd.fff}"; //The mouse stays on the data point and the XY value is displayed series1.Name = "PT1000 temperature"; series1.ChartType = SeriesChartType.Spline; // type series1.BorderWidth = 2; //Line width series1.Color = Color.Red; //Line color series1.XValueType = ChartValueType.DateTime; //Display time series1.YValueType = ChartValueType.Auto; series1.IsValueShownAsLabel = true; //Display data value series1.LabelFormat = "F1"; //Display data format series1.LabelForeColor = Color.Black; //Display data color series1.LabelBackColor = Color.AliceBlue; //Display data background color //Marker series1.MarkerStyle = MarkerStyle.Square; //Label point style series1.MarkerSize = 5; series1.MarkerColor = Color.Black; //label point color //icon legend //Dock chart1.Legends[0].Alignment = StringAlignment.Far; //To the right chart1.Legends[0].Docking = Docking.Top; //Towards the top } static int range = 0; Random r = new Random(6); int sum = 1; bool flag = false; DateTime dateTime; private void timer1_Tick(object sender, EventArgs e) { if (flag) return; else { range = r.Next(1, 60); //Randomly pick a number dateTime = dateTime.AddMilliseconds(100); series1.Points.AddXY(dateTime, 5 + range); //Set series points chart1.ChartAreas[0].AxisX.ScaleView.Size = dateTime.AddMilliseconds(900).ToOADate() - dateTime.ToOADate(); sum + + ; if (sum <= chart1.ChartAreas[0].AxisX.ScaleView.Size) chart1.ChartAreas[0].AxisX.ScaleView.Position = dateTime.ToOADate(); else chart1.ChartAreas[0].AxisX.ScaleView.Position = dateTime.ToOADate() - chart1.ChartAreas[0].AxisX.ScaleView.Size; //series1.Points.AddXY(sum, 5 + range); //sum + + ; //if (comboBox1.SelectedItem.ToString() == "OverView") //Switch view //{ // chart1.ChartAreas[0].AxisX.ScaleView.Position = 1; // if (sum > 10) // { // double max = chart1.ChartAreas[0].AxisX.Maximum; // max = (sum / 10 + 1) * 10; // chart1.ChartAreas[0].AxisX.Interval = max / 10; // } // chart1.ChartAreas[0].AxisX.ScaleView.Size = sum * 1.1; // //chart.ChartAreas[0].AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.None;//Enable the X-axis scroll bar button //} //if (comboBox1.SelectedItem.ToString() == "Follow") //{ // //chart1.ChartAreas[0].AxisX.Interval = 1D; // chart1.ChartAreas[0].AxisX.ScaleView.Size = 10D; // if (sum <= chart1.ChartAreas[0].AxisX.ScaleView.Size) // chart1.ChartAreas[0].AxisX.ScaleView.Position = 1; //else // chart1.ChartAreas[0].AxisX.ScaleView.Position = sum - chart1.ChartAreas[0].AxisX.ScaleView.Size; //} } } private void button1_Click(object sender, EventArgs e) { if (button1.Text == "Start") { timer1.Start(); button1.Text = "Pause"; } else { timer1.Stop(); button1.Text = "Start"; } } private void chart1_SelectionRangeChanged(object sender, CursorEventArgs e) { //Return when there is no data if (chart1.Series[0].Points.Count == 0) return; double start_position = 0.0; double end_position = 0.0; double myInterval = 0.0; start_position = e.NewSelectionStart; end_position = e.NewSelectionEnd; myInterval = Math.Abs(start_position - end_position); Console.WriteLine(start_position.ToString() + " " + end_position.ToString() + " " + myInterval.ToString()); //if (myInterval == 0.0) // return; X-axis view starting point //chart1.ChartAreas[0].AxisX.ScaleView.Position = Math.Min(start_position, end_position); X-axis view length //chart1.ChartAreas[0].AxisX.ScaleView.Size = myInterval; X-axis interval //if (myInterval < dateTime.AddMilliseconds(900).ToOADate() - dateTime.ToOADate()) //{ // chart1.ChartAreas[0].AxisX.Interval = 100; //} //else //{ // chart1.ChartAreas[0].AxisX.Interval = Math.Floor(myInterval / 10); //} //flag = true; //if (!comboBox1.Items.Contains("Zoom")) //{ // comboBox1.Items.Add("Zoom"); // comboBox1.SelectedItem = "Zoom"; //} } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { if (comboBox1.SelectedItem.ToString() == "Zoom") { flag = true; } else if (comboBox1.SelectedItem.ToString() == "OverView" || comboBox1.SelectedItem.ToString() == "Follow") { comboBox1.Items.Remove("Zoom"); flag = false; } } Point lastPoint = new Point();//Coordinates of the last point ToolTip tp = new ToolTip();//tooltip display bar //Draw vertical line coordinates Point p1 = new Point(0, 0); Point p2 = new Point(0, 0); //////Mouse move event /// /// /// private void chart1_MouseMove(object sender, MouseEventArgs e) { this.Refresh();//Refresh the chart, using clear will completely clear the graphics on the chart Pen pen = new Pen(Color.Yellow); Graphics g = chart1.CreateGraphics(); string seriesInfo = ""; //tooltip text if (e.Location != lastPoint)//If no operation is performed at the last point, the operation here will trigger the refresh operation of the chart control and cause the interface to flicker. { for (int y = 0; y <= chart1.Size.Height; y + + )//Line range for collision detection { HitTestResult result = chart1.HitTest(e.X, y); if (result.ChartElementType == ChartElementType.DataPoint) { foreach (DataPoint dpp in result.Series.Points)//Default style of data points. Occasionally, the modification cannot be completed normally when modified using the index method. { dpp.MarkerStyle = MarkerStyle.Diamond; dpp.MarkerColor = Color.White; dpp.MarkerSize = 5; } int i = result.PointIndex; DataPoint dp = result.Series.Points[i]; dp.MarkerStyle = MarkerStyle.Star4;//The style of captured data points dp.MarkerColor = Color.Orange; dp.MarkerSize = 15; //Get the relative coordinates of the data point p1 = new Point((int)chart1.ChartAreas[0].AxisX.ValueToPixelPosition(dp.XValue), 0); p2 = new Point((int)chart1.ChartAreas[0].AxisX.ValueToPixelPosition(dp.XValue), chart1.Size.Height); seriesInfo = string.Format("Item: {0} Time: {1} Energy consumption value: {2}", result.Series.LegendText, DateTime.FromOADate(dp.XValue), dp.YValues[0] ); break; } } tp.AutoPopDelay = 5000;//Show tooltip tp.ShowAlways = false; tp.IsBalloon = true; tp.SetToolTip(chart1, seriesInfo); } lastPoint = e.Location;//Record this location g.DrawLine(pen, p1, p2);//Draw a vertical line } } }
Design interface
Events that need to be added
final effect
magnification effect
The auxiliary lines are not associated and can be associated according to the actual situation.
Crossing the river by feeling the stones, thanks to other bloggers for providing code, long live open source!