庫的下載
項目的引用右鍵,選擇“管理NuGet程序包”,搜索OxyPlot,安裝OxyPlot.WindowsForms
或者直接引用OxyPlot.dll,和OxyPlot.WIndowsForms.dll文件,在此處下載。
HelloWorld
首先在Form上創建一個PlotView控件,暫時無法直接拖入。
可以在InitializeComponent下調用InitPlot();
private void InitPlot() { this.plot1 = new OxyPlot.WindowsForms.PlotView(); this.SuspendLayout(); this.plot1.Dock = System.Windows.Forms.DockStyle.Fill; this.plot1.Location = new System.Drawing.Point(0, 0); this.plot1.Name = "plot1"; this.plot1.TabIndex = 0; this.plot1.Margin = new System.Windows.Forms.Padding(0); this.Controls.Add(this.plot1); this.ResumeLayout(); }
注意:如果是在Form的一個Panel下添加PlotView,
可以這樣
this.panel1.Controls.Add(this.plot1);
然后創建Model,整體代碼如下
public Form1() { InitializeComponent(); InitPlot(); var myModel = new PlotModel { Title = "Example 1" }; myModel.Series.Add(new FunctionSeries(Math.Cos, 0, 10, 0.1, "cos(x)")); this.plot1.Model = myModel; }
改變背景色,添加曲線
var myModel = new PlotModel { Title = "Example 1" ,Background=OxyColors.White}; myModel.Series.Add(new FunctionSeries(Math.Cos, 0, 10, 0.1, "cos(x)")); myModel.Series.Add(new FunctionSeries(Math.Sin, -10, 10, 0.1, "sin(x)")); myModel.Series.Add(new FunctionSeries(t => 5 * Math.Cos(t), t => 5 * Math.Sin(t), 0, 2 * Math.PI, 0.1, "cos(t),sin(t)")); this.plot1.Model = myModel;
一個實時更新曲線的例子
來源https://blog.csdn.net/weixin_42930928/article/details/81706540

public partial class Form1 : Form { private PlotView plot1; public Form1() { InitializeComponent(); InitPlot(); } private void InitPlot() { this.plot1 = new OxyPlot.WindowsForms.PlotView(); this.SuspendLayout(); this.plot1.Dock = System.Windows.Forms.DockStyle.Fill; this.plot1.Location = new System.Drawing.Point(0, 0); this.plot1.Name = "plot1"; this.plot1.TabIndex = 0; this.plot1.Margin = new System.Windows.Forms.Padding(0); this.panel1.Controls.Add(this.plot1); this.ResumeLayout(); } private PlotModel _myPlotModel; private DateTimeAxis _dateAxis; private LinearAxis _valueAxis; private Random rand = new Random(); private void Form1_Load(object sender, EventArgs e) { _myPlotModel = new PlotModel() { Title = "Temp & Humi", LegendTitle = "Legend", LegendOrientation = LegendOrientation.Horizontal, LegendPlacement = LegendPlacement.Inside, LegendPosition = LegendPosition.TopRight, LegendBackground = OxyColor.FromAColor(200, OxyColors.Beige), LegendBorder = OxyColors.Black }; //X軸 _dateAxis = new DateTimeAxis() { MajorGridlineStyle = LineStyle.Solid, MinorGridlineStyle = LineStyle.Dot, IntervalLength = 80, //IsZoomEnabled = false, //IsPanEnabled = false }; _myPlotModel.Axes.Add(_dateAxis); //Y軸 _valueAxis = new LinearAxis() { MajorGridlineStyle = LineStyle.Solid, MinorGridlineStyle = LineStyle.Dot, IntervalLength = 80, Angle = 60, IsZoomEnabled = false, IsPanEnabled = false, Maximum = 100, Minimum = -1 }; _myPlotModel.Axes.Add(_valueAxis); //添加標注線,溫度上下限和濕度上下限 var lineTempMaxAnnotation = new OxyPlot.Annotations.LineAnnotation() { Type = LineAnnotationType.Horizontal, Color = OxyColors.Red, LineStyle = LineStyle.Solid, Y = 10, Text = "Temp MAX:10" }; _myPlotModel.Annotations.Add(lineTempMaxAnnotation); var lineTempMinAnnotation = new LineAnnotation() { Type = LineAnnotationType.Horizontal, Y = 30, Text = "Temp Min:30", Color = OxyColors.Red, LineStyle = LineStyle.Solid }; _myPlotModel.Annotations.Add(lineTempMinAnnotation); var lineHumiMaxAnnotation = new OxyPlot.Annotations.LineAnnotation() { Type = LineAnnotationType.Horizontal, Color = OxyColors.Red, LineStyle = LineStyle.Solid, //lineMaxAnnotation.MaximumX = 0.8; Y = 75, Text = "Humi MAX:75" }; _myPlotModel.Annotations.Add(lineHumiMaxAnnotation); var lineHumiMinAnnotation = new LineAnnotation() { Type = LineAnnotationType.Horizontal, Y = 35, Text = "Humi Min:35", Color = OxyColors.Red, LineStyle = LineStyle.Solid }; _myPlotModel.Annotations.Add(lineHumiMinAnnotation); //添加兩條曲線 var series = new LineSeries() { Color = OxyColors.Green, StrokeThickness = 2, MarkerSize = 3, MarkerStroke = OxyColors.DarkGreen, MarkerType = MarkerType.Diamond, Title = "Temp", }; _myPlotModel.Series.Add(series); series = new LineSeries() { Color = OxyColors.Blue, StrokeThickness = 2, MarkerSize = 3, MarkerStroke = OxyColors.BlueViolet, MarkerType = MarkerType.Star, Title = "Humi", }; _myPlotModel.Series.Add(series); plot1.Model = _myPlotModel; Task.Factory.StartNew(() => { while (true) { var date = DateTime.Now; _myPlotModel.Axes[0].Maximum = DateTimeAxis.ToDouble(date.AddSeconds(1)); var lineSer = plot1.Model.Series[0] as LineSeries; lineSer.Points.Add(new DataPoint(DateTimeAxis.ToDouble(date), rand.Next(100, 300) / 10.0)); if (lineSer.Points.Count > 100) { lineSer.Points.RemoveAt(0); } lineSer = plot1.Model.Series[1] as LineSeries; lineSer.Points.Add(new DataPoint(DateTimeAxis.ToDouble(date), rand.Next(350, 750) / 10.0)); if (lineSer.Points.Count > 100) { lineSer.Points.RemoveAt(0); } _myPlotModel.InvalidatePlot(true); Thread.Sleep(1000); } }); } }
Tricks
LinearAxis的父類中有
AbsoluteMaximum和AbsoluteMinimum
用來UI 控制,超過此范圍Pan 和zoom無效。
不管你如何Pan,Zoom,將最新數據顯示在最右側的辦法
以上面例子,每隔一秒,X 軸的Maximum參數增加一秒,
要讓用戶移動之后,讓最新數據自動歸位到最右側,只需要在InvalidDatePlot之前調用_myPlotModel.ResetAllAxes();
原理:Axis 中的ViewMinimum和ViewMaximun(就是實際看到的)只有在Minimum和Maximum沒有指定的時候才會重新計算,
ResetAllAxes之后,ViewMinimum和ViewMaximum根據當前Minimum的和Maximum的 數據重新計算。
(實際雙擊鼠標中鍵起同樣作用)
默認右鍵移動坐標,換成左鍵
var myController = new PlotController(); myController.UnbindMouseDown(OxyMouseButton.Right); myController.BindMouseDown(OxyMouseButton.Left, PlotCommands.PanAt); plot1.Controller = myController;
點擊鼠標獲取屏幕坐標和坐標系坐標
plot1.Model.MouseDown += Model_MouseDown; private void Model_MouseDown(object sender, OxyMouseDownEventArgs e) { //double x = e.Position.X; //double y = e.Position.Y; DataPoint p=OxyPlot.Axes.Axis.InverseTransform(e.Position, plot1.Model.DefaultXAxis, plot1.Model.DefaultYAxis); this.Text=($"X is {x} and Y is {y} and Inverse is {p.ToString()}"); }
隱藏坐標軸
創建Axis對象時,IsAxisVisible 設置為false
防止zoom過於放大
在創建軸的時候,設置MinimumRange,
坐標軸的刻度線
分為大刻度線Major 和小刻度線Minor
默認將顯示的坐標軸划分為7大段(MajorTickSize)
每個大段划分為4小段(MinorTickSize),這2個值都可以設置。注意MajorTickSize設置得太大可能無效,因為要保證Label顯示的美觀。
在創建Axis對象時,只需要設置MajorGridLineStyle即可繪制垂直於該軸的線條。比如LineStyle.Solid
如果使用了MajorStep和MinorStep,上面的(MajorTickSize和MinorTickSize就會無效)。
會按照坐標系的值,每隔一個MajorStep的值,繪制大刻度線,繪制label。然后同理用MinorStep繪制小刻度線。
繪制隨時間更新的紅線
var lineAnnotation = new LineAnnotation() { Type=LineAnnotationType.Vertical, X=100, Text="Current Time", Color=OxyColors.Red, LineStyle=LineStyle.Solid }; model.Annotations.Add(lineAnnotation); //當時間變化時 (plot1.Model.Annotations[0] as LineAnnotation).X+=30; plot1.Model.InvalidatePlot(true);
綜上,繪制自定義Chart
namespace OxyTestFirst { public partial class Form1 : Form { private PlotView plot1; public Form1() { InitializeComponent(); InitPlot(); } private void InitPlot() { this.plot1 = new OxyPlot.WindowsForms.PlotView(); this.SuspendLayout(); this.plot1.Dock = System.Windows.Forms.DockStyle.Fill; this.plot1.Location = new System.Drawing.Point(0, 0); this.plot1.Name = "plot1"; this.plot1.TabIndex = 0; this.plot1.Margin = new System.Windows.Forms.Padding(0); this.panel1.Controls.Add(this.plot1); this.ResumeLayout(); } //private PlotModel _myPlotModel; //private DateTimeAxis _dateAxis; //private LinearAxis _valueAxis; //private Random rand = new Random(); private void Form1_Load(object sender, EventArgs e) { int samples = 5; int distance = 179; int rectPad = 34; var model = new PlotModel() { Background = OxyColors.White, Title = "Schedule 1", TitleFont= "Arial", TitlePadding=16 }; model.Axes.Add(new LinearAxis { Title="Samples", AxisTitleDistance=16, TitleFontSize=16, Position = AxisPosition.Left, AbsoluteMaximum=samples*distance, Maximum=samples*distance, AbsoluteMinimum=0,MinimumRange=1, MajorStep=distance, MinorStep=distance, LabelFormatter=y=> { int Nr = samples - (int)y / distance + 1; return Nr > samples ? "" : Nr.ToString(); } }); model.Axes.Add(new LinearAxis { Title="Runtime", AxisTitleDistance = 16, TitleFontSize = 16, Minimum = 0, Maximum=1500, AbsoluteMinimum=0, MinimumRange=5, Position = AxisPosition.Bottom, MajorTickSize=15, MinorTickSize=5, MajorGridlineStyle=LineStyle.Solid, MajorGridlineColor=OxyColors.LightGray, LabelFormatter = time => { int hour = 0; int min = 0; int sec = 0; sec = (int)time; if (sec >= 60) { min = ((int)sec) / 60; sec = sec % 60; } if (min >= 60) { hour = min / 60; min = min % 60; } return string.Format("{0:D2}:{1:D2}:{2:D2}", hour, min, sec); } }) ; var lineAnnotation = new LineAnnotation() { Type=LineAnnotationType.Vertical, X=100, Text="當前時間", Color=OxyColors.Red, LineStyle=LineStyle.Solid }; model.Annotations.Add(lineAnnotation); var rect1 = new RectangleAnnotation() { MinimumX = 0, MaximumX = 5.9, MinimumY = distance * (samples - 1) + rectPad, MaximumY = distance * (samples) - rectPad, Fill = OxyColor.FromRgb(155, 188, 243),//sky blue Stroke=OxyColors.Transparent }; model.Annotations.Add(rect1); var rect2 = new RectangleAnnotation() { MinimumX = 6, MaximumX = 180, MinimumY = distance * (samples - 1) + 1.5*rectPad, MaximumY = distance * (samples) - 1.5*rectPad, Fill = OxyColor.FromRgb(191, 2, 1),//red Stroke = OxyColors.Transparent }; var rect3 = new RectangleAnnotation() { MinimumX = 180.1, MaximumX = 240, MinimumY = distance * (samples - 1) + rectPad, MaximumY = distance * (samples) - rectPad, Fill = OxyColor.FromRgb(254, 152, 14), Stroke = OxyColors.Transparent//organge }; var rect4 = new RectangleAnnotation() { MinimumX = 180.1, MaximumX = 480, MinimumY = distance * (samples - 1) + 1.5 * rectPad, MaximumY = distance * (samples) - 1.5 * rectPad, Fill = OxyColor.FromRgb(254, 191, 20),//yellow Stroke = OxyColors.Transparent }; model.Annotations.Add(rect3); model.Annotations.Add(rect2); model.Annotations.Add(rect4); var myController = new PlotController(); myController.UnbindMouseDown(OxyMouseButton.Right); myController.BindMouseDown(OxyMouseButton.Left, PlotCommands.PanAt); plot1.Controller = myController; //plot1.Model = Example.RectangleAnnotation(); plot1.Model = model; plot1.Model.MouseDown += Model_MouseDown; } private void Model_MouseDown(object sender, OxyMouseDownEventArgs e) { double x = e.Position.X; double y = e.Position.Y; DataPoint p=OxyPlot.Axes.Axis.InverseTransform(e.Position, plot1.Model.DefaultXAxis, plot1.Model.DefaultYAxis); this.Text=($"X is {x} and Y is {y} and Inverse is {p.ToString()}"); } } }