diff --git a/Bin/net40/SunnyUI.Demo.exe b/Bin/net40/SunnyUI.Demo.exe index 4a5b4d78..160c6d17 100644 Binary files a/Bin/net40/SunnyUI.Demo.exe and b/Bin/net40/SunnyUI.Demo.exe differ diff --git a/Bin/net40/SunnyUI.dll b/Bin/net40/SunnyUI.dll index 2dbbb230..38895f99 100644 Binary files a/Bin/net40/SunnyUI.dll and b/Bin/net40/SunnyUI.dll differ diff --git a/SunnyUI.Demo/Charts/FLineChart.Designer.cs b/SunnyUI.Demo/Charts/FLineChart.Designer.cs index a21e756b..71f90faf 100644 --- a/SunnyUI.Demo/Charts/FLineChart.Designer.cs +++ b/SunnyUI.Demo/Charts/FLineChart.Designer.cs @@ -36,8 +36,8 @@ this.LineChart = new Sunny.UI.UILineChart(); this.uiSymbolButton2 = new Sunny.UI.UISymbolButton(); this.timer1 = new System.Windows.Forms.Timer(this.components); - this.uiCheckBox1 = new Sunny.UI.UICheckBox(); - this.uiSymbolButton3 = new Sunny.UI.UISymbolButton(); + this.cbPoints = new Sunny.UI.UICheckBox(); + this.cbContainsNan = new Sunny.UI.UICheckBox(); ((System.ComponentModel.ISupportInitialize)(this.uiImageButton3)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.uiImageButton2)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.uiImageButton1)).BeginInit(); @@ -132,41 +132,39 @@ // this.timer1.Tick += new System.EventHandler(this.timer1_Tick); // - // uiCheckBox1 + // cbPoints // - this.uiCheckBox1.Cursor = System.Windows.Forms.Cursors.Hand; - this.uiCheckBox1.Font = new System.Drawing.Font("微软雅黑", 12F); - this.uiCheckBox1.Location = new System.Drawing.Point(571, 505); - this.uiCheckBox1.MinimumSize = new System.Drawing.Size(1, 1); - this.uiCheckBox1.Name = "uiCheckBox1"; - this.uiCheckBox1.Padding = new System.Windows.Forms.Padding(22, 0, 0, 0); - this.uiCheckBox1.Size = new System.Drawing.Size(100, 29); - this.uiCheckBox1.TabIndex = 37; - this.uiCheckBox1.Text = "显示点"; - this.uiCheckBox1.CheckedChanged += new System.EventHandler(this.uiCheckBox1_CheckedChanged); + this.cbPoints.Cursor = System.Windows.Forms.Cursors.Hand; + this.cbPoints.Font = new System.Drawing.Font("微软雅黑", 12F); + this.cbPoints.Location = new System.Drawing.Point(571, 505); + this.cbPoints.MinimumSize = new System.Drawing.Size(1, 1); + this.cbPoints.Name = "cbPoints"; + this.cbPoints.Padding = new System.Windows.Forms.Padding(22, 0, 0, 0); + this.cbPoints.Size = new System.Drawing.Size(95, 27); + this.cbPoints.TabIndex = 37; + this.cbPoints.Text = "只显示点"; + this.cbPoints.CheckedChanged += new System.EventHandler(this.uiCheckBox1_CheckedChanged); // - // uiSymbolButton3 + // cbContainsNan // - this.uiSymbolButton3.Cursor = System.Windows.Forms.Cursors.Hand; - this.uiSymbolButton3.Font = new System.Drawing.Font("微软雅黑", 12F); - this.uiSymbolButton3.Location = new System.Drawing.Point(665, 505); - this.uiSymbolButton3.MinimumSize = new System.Drawing.Size(1, 1); - this.uiSymbolButton3.Name = "uiSymbolButton3"; - this.uiSymbolButton3.Padding = new System.Windows.Forms.Padding(28, 0, 0, 0); - this.uiSymbolButton3.Size = new System.Drawing.Size(100, 27); - this.uiSymbolButton3.Symbol = 61952; - this.uiSymbolButton3.TabIndex = 38; - this.uiSymbolButton3.Text = "数据"; - this.uiSymbolButton3.Visible = false; - this.uiSymbolButton3.Click += new System.EventHandler(this.uiSymbolButton3_Click); + this.cbContainsNan.Cursor = System.Windows.Forms.Cursors.Hand; + this.cbContainsNan.Font = new System.Drawing.Font("微软雅黑", 12F); + this.cbContainsNan.Location = new System.Drawing.Point(571, 535); + this.cbContainsNan.MinimumSize = new System.Drawing.Size(1, 1); + this.cbContainsNan.Name = "cbContainsNan"; + this.cbContainsNan.Padding = new System.Windows.Forms.Padding(22, 0, 0, 0); + this.cbContainsNan.Size = new System.Drawing.Size(95, 27); + this.cbContainsNan.TabIndex = 38; + this.cbContainsNan.Text = "包含Nan"; + this.cbContainsNan.CheckedChanged += new System.EventHandler(this.uiCheckBox2_CheckedChanged); // // FLineChart // this.AllowShowTitle = true; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; this.ClientSize = new System.Drawing.Size(800, 574); - this.Controls.Add(this.uiSymbolButton3); - this.Controls.Add(this.uiCheckBox1); + this.Controls.Add(this.cbContainsNan); + this.Controls.Add(this.cbPoints); this.Controls.Add(this.uiSymbolButton2); this.Controls.Add(this.uiSymbolButton1); this.Controls.Add(this.uiImageButton3); @@ -194,7 +192,7 @@ private UILineChart LineChart; private UISymbolButton uiSymbolButton2; private System.Windows.Forms.Timer timer1; - private UICheckBox uiCheckBox1; - private UISymbolButton uiSymbolButton3; + private UICheckBox cbPoints; + private UICheckBox cbContainsNan; } } \ No newline at end of file diff --git a/SunnyUI.Demo/Charts/FLineChart.cs b/SunnyUI.Demo/Charts/FLineChart.cs index a699141e..cb48acfd 100644 --- a/SunnyUI.Demo/Charts/FLineChart.cs +++ b/SunnyUI.Demo/Charts/FLineChart.cs @@ -29,13 +29,14 @@ namespace Sunny.UI.Demo series.Add(dt.AddHours(0), 1.2); series.Add(dt.AddHours(1), 2.2); series.Add(dt.AddHours(2), 3.2); - series.Add(dt.AddHours(3), 4.2); + series.Add(dt.AddHours(3), cbContainsNan.Checked ? double.NaN : 4.2); series.Add(dt.AddHours(4), 3.2); series.Add(dt.AddHours(5), 2.2); series.Symbol = UILinePointSymbol.Square; series.SymbolSize = 4; series.SymbolLineWidth = 2; series.SymbolColor = Color.Red; + series.ShowLine = !cbPoints.Checked; series = option.AddSeries(new UILineSeries("Line2", Color.Lime)); series.Add(dt.AddHours(3), 3.3); @@ -49,6 +50,7 @@ namespace Sunny.UI.Demo series.SymbolLineWidth = 2; series.SymbolColor = Color.Red; series.Smooth = true; + series.ShowLine = !cbPoints.Checked; option.GreaterWarningArea = new UILineWarningArea(3.5); option.LessWarningArea = new UILineWarningArea(2.2, Color.Gold); @@ -135,14 +137,7 @@ namespace Sunny.UI.Demo private void uiCheckBox1_CheckedChanged(object sender, EventArgs e) { - if (LineChart.Option == null) return; - foreach (var series in LineChart.Option.Series.Values) - { - series.ShowLine = !uiCheckBox1.Checked; - series.Symbol = uiCheckBox1.Checked ? UILinePointSymbol.Circle : UILinePointSymbol.None; - } - - LineChart.Refresh(); + uiSymbolButton1.PerformClick(); } private void uiSymbolButton3_Click(object sender, EventArgs e) @@ -166,7 +161,6 @@ namespace Sunny.UI.Demo series.SymbolSize = 4; series.SymbolLineWidth = 2; series.SymbolColor = Color.Red; - series.ContainsNan = true; option.XAxis.Name = "日期"; option.YAxis.Name = "数值"; @@ -177,5 +171,10 @@ namespace Sunny.UI.Demo LineChart.SetOption(option); } + + private void uiCheckBox2_CheckedChanged(object sender, EventArgs e) + { + uiSymbolButton1.PerformClick(); + } } } diff --git a/SunnyUI.Demo/FMain.cs b/SunnyUI.Demo/FMain.cs index 94906fd9..94f85f40 100644 --- a/SunnyUI.Demo/FMain.cs +++ b/SunnyUI.Demo/FMain.cs @@ -54,10 +54,10 @@ namespace Sunny.UI.Demo Header.SetNodeSymbol(Header.Nodes[2], 61950); parent = Aside.CreateNode("图表", 61950, 24, pageIndex); //直接关联(默认自动生成GUID) - Aside.CreateChildNode(parent, AddPage(new FPieChart())); - Aside.CreateChildNode(parent, AddPage(new FDoughnutChart())); Aside.CreateChildNode(parent, AddPage(new FBarChart())); + Aside.CreateChildNode(parent, AddPage(new FDoughnutChart())); Aside.CreateChildNode(parent, AddPage(new FLineChart())); + Aside.CreateChildNode(parent, AddPage(new FPieChart())); pageIndex = 4000; Header.SetNodePageIndex(Header.Nodes[3], pageIndex); diff --git a/SunnyUI/Charts/UIBarChart.cs b/SunnyUI/Charts/UIBarChart.cs index 29c1c5fe..a012bab1 100644 --- a/SunnyUI/Charts/UIBarChart.cs +++ b/SunnyUI/Charts/UIBarChart.cs @@ -133,11 +133,6 @@ namespace Sunny.UI Bars.Clear(); NeedDraw = false; if (Option == null || Option.Series == null || Option.SeriesCount == 0) return; - - DrawOrigin = new Point(Option.Grid.Left, Height - Option.Grid.Bottom); - DrawSize = new Size(Width - Option.Grid.Left - Option.Grid.Right, - Height - Option.Grid.Top - Option.Grid.Bottom); - if (DrawSize.Width <= 0 || DrawSize.Height <= 0) return; if (Option.XAxis.Data.Count == 0) return; @@ -282,9 +277,11 @@ namespace Sunny.UI } } + protected Point DrawOrigin => new Point(Option.Grid.Left, Height - Option.Grid.Bottom); + protected Size DrawSize => new Size(Width - Option.Grid.Left - Option.Grid.Right, Height - Option.Grid.Top - Option.Grid.Bottom); + protected Rectangle DrawRect => new Rectangle(Option.Grid.Left, Option.Grid.Top, DrawSize.Width, DrawSize.Height); + protected int selectIndex = -1; - protected Point DrawOrigin; - protected Size DrawSize; protected float DrawBarWidth; protected int YAxisStart; protected int YAxisEnd; diff --git a/SunnyUI/Charts/UIBarChartEx.cs b/SunnyUI/Charts/UIBarChartEx.cs index b04425f3..36630fc0 100644 --- a/SunnyUI/Charts/UIBarChartEx.cs +++ b/SunnyUI/Charts/UIBarChartEx.cs @@ -37,11 +37,6 @@ namespace Sunny.UI Bars.Clear(); NeedDraw = false; if (Option == null || Option.Series == null || Option.SeriesCount == 0) return; - - DrawOrigin = new Point(Option.Grid.Left, Height - Option.Grid.Bottom); - DrawSize = new Size(Width - Option.Grid.Left - Option.Grid.Right, - Height - Option.Grid.Top - Option.Grid.Bottom); - if (DrawSize.Width <= 0 || DrawSize.Height <= 0) return; if (Option.Series.Count == 0) return; diff --git a/SunnyUI/Charts/UILineChart.cs b/SunnyUI/Charts/UILineChart.cs index bb376f6e..9f0ce29b 100644 --- a/SunnyUI/Charts/UILineChart.cs +++ b/SunnyUI/Charts/UILineChart.cs @@ -46,30 +46,25 @@ namespace Sunny.UI CalcData(); } - protected Point DrawOrigin; - protected Size DrawSize; - private Rectangle DrawRect; + [Browsable(false)] + public Point DrawOrigin => new Point(Option.Grid.Left, Height - Option.Grid.Bottom); + + [Browsable(false)] + public Size DrawSize => new Size(Width - Option.Grid.Left - Option.Grid.Right, Height - Option.Grid.Top - Option.Grid.Bottom); + + [Browsable(false)] + public Rectangle DrawRect => new Rectangle(Option.Grid.Left, Option.Grid.Top, DrawSize.Width, DrawSize.Height); protected override void CalcData() { NeedDraw = false; if (Option?.Series == null || Option.Series.Count == 0) return; - - DrawOrigin = new Point(Option.Grid.Left, Height - Option.Grid.Bottom); - DrawSize = new Size(Width - Option.Grid.Left - Option.Grid.Right, - Height - Option.Grid.Top - Option.Grid.Bottom); - DrawRect = new Rectangle(Option.Grid.Left, Option.Grid.Top, DrawSize.Width, DrawSize.Height); - - if (DrawSize.Width <= 0 || DrawSize.Height <= 0) return; CalcAxises(); foreach (var series in Option.Series.Values) { - series.ClearPoints(); - float[] x = XScale.CalcXPixels(series.XData.ToArray(), DrawOrigin.X, DrawSize.Width); - float[] y = YScale.CalcYPixels(series.YData.ToArray(), DrawOrigin.Y, DrawSize.Height); - series.AddPoints(x, y); + series.CalcData(this, XScale, YScale); } NeedDraw = true; @@ -199,6 +194,7 @@ namespace Sunny.UI DrawLegend(g, Option.Legend); DrawAxis(g); DrawAxisScales(g); + DrawPointSymbols(g); DrawOther(g); } @@ -396,18 +392,14 @@ namespace Sunny.UI if (Option.GreaterWarningArea != null) { - using (Graphics graphics = bmpGreater.Graphics()) - { - DrawSeries(graphics, Option.GreaterWarningArea.Color, series); - } + using Graphics graphics = bmpGreater.Graphics(); + DrawSeries(graphics, Option.GreaterWarningArea.Color, series); } if (Option.LessWarningArea != null) { - using (Graphics graphics = bmpLess.Graphics()) - { - DrawSeries(graphics, Option.LessWarningArea.Color, series); - } + using Graphics graphics = bmpLess.Graphics(); + DrawSeries(graphics, Option.LessWarningArea.Color, series); } idx++; @@ -449,7 +441,12 @@ namespace Sunny.UI g.DrawImage(bmp, new Rectangle((int)wLeft, (int)wTop, (int)(wRight - wLeft), (int)(wBottom - wTop)), new Rectangle((int)wLeft, (int)wTop, (int)(wRight - wLeft), (int)(wBottom - wTop)), GraphicsUnit.Pixel); - idx = 0; + + } + + private void DrawPointSymbols(Graphics g) + { + int idx = 0; foreach (var series in Option.Series.Values) { Color color = series.Color; @@ -462,8 +459,8 @@ namespace Sunny.UI { foreach (var p in series.Points) { - if (p.X <= Option.Grid.Left || p.X >= Width - Option.Grid.Right) continue; - if (p.Y <= Option.Grid.Top || p.Y >= Height - Option.Grid.Bottom) continue; + if (p.X < Option.Grid.Left || p.X > Width - Option.Grid.Right) continue; + if (p.Y < Option.Grid.Top || p.Y > Height - Option.Grid.Bottom) continue; if (double.IsNaN(p.X) || double.IsNaN(p.Y)) continue; switch (series.Symbol) @@ -538,7 +535,7 @@ namespace Sunny.UI using (Pen pn = new Pen(line.Color, line.Size)) { - g.DrawLine(pn, DrawOrigin.X, pos, Width - Option.Grid.Right, pos); + g.DrawLine(pn, DrawOrigin.X + 1, pos, Width - Option.Grid.Right - 1, pos); } SizeF sf = g.MeasureString(line.Name, SubFont); @@ -559,7 +556,7 @@ namespace Sunny.UI using (Pen pn = new Pen(line.Color, line.Size)) { - g.DrawLine(pn, pos, DrawOrigin.Y, pos, Option.Grid.Top); + g.DrawLine(pn, pos, DrawOrigin.Y - 1, pos, Option.Grid.Top + 1); } SizeF sf = g.MeasureString(line.Name, SubFont); diff --git a/SunnyUI/Charts/UILineChartOption.cs b/SunnyUI/Charts/UILineChartOption.cs index d7202873..66f767fb 100644 --- a/SunnyUI/Charts/UILineChartOption.cs +++ b/SunnyUI/Charts/UILineChartOption.cs @@ -288,7 +288,7 @@ namespace Sunny.UI public bool ShowLine { get; set; } = true; - public bool ContainsNan { get; set; } + public bool ContainsNan { get; private set; } public UILineSeries(string name) { @@ -354,12 +354,13 @@ namespace Sunny.UI public void Clear() { + ContainsNan = false; XData.Clear(); YData.Clear(); ClearPoints(); } - public void ClearPoints() + private void ClearPoints() { Points.Clear(); PointsX.Clear(); @@ -383,10 +384,19 @@ namespace Sunny.UI } } + public void CalcData(UILineChart chart, UIScale XScale, UIScale YScale) + { + ClearPoints(); + float[] x = XScale.CalcXPixels(XData.ToArray(), chart.DrawOrigin.X, chart.DrawSize.Width); + float[] y = YScale.CalcYPixels(YData.ToArray(), chart.DrawOrigin.Y, chart.DrawSize.Height); + AddPoints(x, y); + } + public void Add(double x, double y) { XData.Add(x); - if (double.IsInfinity(y)) y = double.NaN; + if (y.IsInfinity()) y = double.NaN; + if (y.IsNan()) ContainsNan = true; YData.Add(y); } @@ -394,7 +404,8 @@ namespace Sunny.UI { DateTimeInt64 t = new DateTimeInt64(x); XData.Add(t); - if (double.IsInfinity(y)) y = double.NaN; + if (y.IsInfinity()) y = double.NaN; + if (y.IsNan()) ContainsNan = true; YData.Add(y); } @@ -402,7 +413,8 @@ namespace Sunny.UI { int cnt = XData.Count; XData.Add(cnt); - if (double.IsInfinity(y)) y = double.NaN; + if (y.IsInfinity()) y = double.NaN; + if (y.IsNan()) ContainsNan = true; YData.Add(y); } }