天天看點

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

Prepare

 本文将使用一個NuGet公開的元件來實作曲線的顯示,包含了多種顯示的模式和配置來滿足各種不同的應用場景,友善大家進行快速的開發系統。

 聯系作者及加群方式(激活碼在群裡發放):http://www.hslcommunication.cn/Cooperation

在Visual Studio 中的NuGet管理器中可以下載下傳安裝,也可以直接在NuGet控制台輸入下面的指令安裝:

Install-Package HslCommunication
      

NuGet安裝教程  http://www.cnblogs.com/dathlin/p/7705014.html

更強大的曆史曲線控件參考:https://www.cnblogs.com/dathlin/p/10291327.html

Summary

曲線控件屬于元件裡諸多控件中的一種,為什麼單獨拿出來寫一篇部落格呢,就是因為曲線控件相對于其他控件都要複雜很多,并不是幾個屬性那麼簡單,下面列舉了本曲線控件的特性:

  • 提供便捷的API調用即可顯示曲線資訊内容,不需要複雜的配置
  • 曲線界面的一些資訊可以自由定制,比如坐标軸的顔色,是否顯示虛線等等
  • 高度的大小自适應,無論你怎麼調整控件的大小,始終都能友好顯示
  • 支援資料拉伸填充和像素點填充兩種模式,具體差別參照下面的代碼
  • 多曲線支援,支援同時顯示多個曲線資訊,每個曲線可獨立的指定顔色,線寬等等。
  • 支援左右兩個參考系,就是說一個控件中允許顯示2種資料跨度不一緻的曲線,每種曲線可以顯示多條不同的曲線

 其他控件的說明位址:http://www.cnblogs.com/dathlin/p/8150516.html

 元件的完整API說明:http://www.cnblogs.com/dathlin/p/7703805.html

要想使用元件的控件,除了使用NuGet來安裝元件外,還需要将元件的dll檔案(在你的項目的packages裡面可以找到,如果你本來就是引用本地的,就直接拖拽本地的即可)拖拽到工具欄:

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

拖拽完成後效果如下:

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

先定義一個方法,擷取指定範圍的,指定個數的随機數數組,供下方的代碼調用

private float[] GetRandomValueByCount( int count, float min, float max )
        {
            float[] data = new float[count];
            for (int i = 0; i < data.Length; i++)
            {
                data[i] = (float)random.NextDouble( ) * (max - min) + min;
            }
            return data;
        }
      

1.單曲線使用

把控件拖拽到視窗界面上去後,現在界面如下,你可以随意的拉伸大小,調整到一個虛線看着比較清晰的時刻停止:

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

我們看到左右縱軸的資料跨度都是0-100,現在我們有個需求,手裡有300個0-200的資料需要顯示,那麼就要先設定左右縱軸的資料跨度

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

接下來就可以編寫顯示的代碼了,一下資料随機:

private void userButton1_Click( object sender, EventArgs e )
        {
            userCurve1.SetLeftCurve( "A", GetRandomValueByCount( 300, 0, 200 ), Color.DodgerBlue );
        }
      

顯示結果如下:

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

看吧,相當簡單友善,如果你覺得目前的資料太密了,想要寬松一點,希望資料拉伸滿整個X軸,沒問題,因為目前預設的模式是像素點模式,是以切換為拉伸模式即可。

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

然後在運作看看效果:

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

接下來我們要對曲線“A”進行資料更新,我們假設你的data數組的資料已經更新了,有可能隻更新了一個資料,有可能全部更新了,在資料更新的時候就不需要在指定顔色了,因為指定了顔色也沒有用了。

private void userButton3_Click( object sender, EventArgs e )
        {
            // 假設你的data數組已經更新了

            // 之前已經給A指定過顔色了,以後後續的資料更新不需要重新指定,指定了也無效
            // 如果需要重新設定顔色,或是線寬,需要先RemoveCurve,然後重新建立曲線資訊
            userCurve1.SetLeftCurve( "A", GetRandomValueByCount( 300, 100, 200 ) );
        }
      
C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

從上面的資料更新我們發現,隻要更新了資料,就不停的調用資料顯示,那麼我們就可以顯示實時資料了,而唯一的麻煩之處在于我們需要維護自己的data數組。是以目前的這種方式隻适合靜态資料顯示

2.舉個經典的例子

當我們需要顯示一些統計資料的時候,比如說我要顯示十二個月的銷售金額,那麼我們應該怎麼寫

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

我們先選擇拉伸模式,然後設定拉伸模式下最大的資料量為12;

private void userButton9_Click( object sender, EventArgs e )
        {
            // 模拟的資料
            string[] text = new string[]
            {
                "一月",
                "二月",
                "三月",
                "四月",
                "五月",
                "六月",
                "七月",
                "八月",
                "九月",
                "十月",
                "十一月",
                "十二月"
            };
            userCurve1.SetCurveText( text );
            userCurve1.SetLeftCurve( "A", GetRandomValueByCount( 12, 0, 200 ), Color.Tomato );            // 每個月使用者1的銷售金額
        }
      

 效果圖如下:

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

 如果我有兩條曲線需要顯示,以友善對比的話:

private void userButton9_Click( object sender, EventArgs e )
        {
            // 模拟的資料
            string[] text = new string[]
            {
                "一月",
                "二月",
                "三月",
                "四月",
                "五月",
                "六月",
                "七月",
                "八月",
                "九月",
                "十月",
                "十一月",
                "十二月"
            };
            userCurve1.SetCurveText( text );
            userCurve1.SetLeftCurve( "A", GetRandomValueByCount( 12, 0, 200 ), Color.Tomato );            // 每個月使用者1的銷售金額
            userCurve1.SetLeftCurve( "B", GetRandomValueByCount( 12, 0, 200 ), Color.DodgerBlue );            // 每個月使用者2的銷售金額
        }
      

 圖形效果如下:

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

即時3條曲線或者是更多的曲線,以此類推。重複設定資料即可,隻是每條曲線的關鍵字需要區分開來。

控件支援移除曲線,主要包含了下面的兩個方法,移除單個的曲線,或者是移除所有的曲線。

userCurve1.RemoveCurve( "A" );  // 移除指定的曲線
            userCurve1.RemoveAllCurve( );   // 移除所有的曲線
      

在上面設定曲線資料的時候發現,是通過調用 SetLeftCurve 方法來設定曲線資訊的,這個方法有個left單詞,很明顯是設定左曲線的,控件裡還有設定右曲線的,SetLeftCurve 方法就是設定右曲線,那麼這裡的左右曲線都是指什麼呢?

我們在上面的曲線控件上看到,縱軸的刻度線分左右兩邊,那麼設定左曲線就是以左邊的刻度線為标準繪制的曲線,而設定右曲線則以右刻度線為标準,在上圖中,左右刻度的資訊是一緻的,是以無所謂左曲線還是右曲線,但是如果我們設定不一緻後,那麼我們就可以實作顯示2種不同範圍的資料資訊,例如我們右曲線設定為0-10,再随便顯示2條曲線

private void userButton9_Click( object sender, EventArgs e )
        {
            // 模拟的資料
            string[] text = new string[]
            {
                "一月",
                "二月",
                "三月",
                "四月",
                "五月",
                "六月",
                "七月",
                "八月",
                "九月",
                "十月",
                "十一月",
                "十二月"
            };
            userCurve1.SetCurveText( text );
            userCurve1.SetLeftCurve( "A", GetRandomValueByCount( 12, 0, 200 ), Color.Tomato );            // 每個月使用者1的銷售金額
            userCurve1.SetLeftCurve( "B", GetRandomValueByCount( 12, 0, 200 ), Color.DodgerBlue );            // 每個月使用者2的銷售金額

            userCurve1.SetRightCurve( "C", GetRandomValueByCount( 12, 3, 6 ), Color.LimeGreen );
            userCurve1.SetRightCurve( "D", GetRandomValueByCount( 12, 3, 6 ), Color.Orchid );
        }
      
C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

進階使用舉例,動态坐标軸,

根據上面的情況,我們看到如果我們擷取到的一組資料,範圍不确定的,需要來動态調整的,比如我們有一個12個資料的float數組,我們設定左坐标軸為資料的上下限

private void userButton10_Click( object sender, EventArgs e )
        {
            // 模拟的資料
            string[] text = new string[]
            {
                "一月",
                "二月",
                "三月",
                "四月",
                "五月",
                "六月",
                "七月",
                "八月",
                "九月",
                "十月",
                "十一月",
                "十二月"
            };

            float[] data = GetRandomValueByCount( 12, 40, 150 );
            userCurve1.ValueMaxLeft = (float)Math.Ceiling( data.Max( ) );// 向上取整
            userCurve1.ValueMinLeft = (float)Math.Floor( data.Min( ) );// 向下取整

            userCurve1.SetCurveText( text );
            userCurve1.SetLeftCurve( "A", data, Color.Tomato );            // 每個月使用者1的銷售金額
        }
      
C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

可以看到,不停的重新整理資料後,左坐标軸的資料一直在更新中。

 總結下:如果每次都是強行更新所有的資料,也能達到實時重新整理的效果,但是如果是一個資料一個資料的采集顯示,将按照下面的實時資料模式使用更加合理

3.實時資料顯示使用

當我們需要顯示一些實時資料時,也就是說,每隔1秒(随便舉個栗子)就有新的資料采集上來,然後追加到曲線中去,曲線進行挪動,通常就是這種情況。

3.1 像素點模式(請确認 IsAbscissaStrech 為False):

我們先講解預設的模式,所謂像素點模式是指在橫軸上,一個像素點顯示一個資料,如果你的橫軸像素長度為1000,那麼你就可以顯示1000個資料了,當然在實時顯示的情況下,不需要你管那麼多,你隻需要負責定期往裡面塞資料即可。

第一步先進行初始化:先增加指定名字的曲線資訊,曲線顔色,曲線寬度等等

private void userButton4_Click( object sender, EventArgs e )
        {
            // 這裡傳入了數組長度為空的資料,不能傳NULL
            userCurve1.SetLeftCurve( "B", new float[] { }, Color.Tomato );
        }
      

我們再寫一個按鈕,啟動定時器,去新增資料,來模拟我們從其他裝置讀取到的資料資訊:

private void userButton5_Click( object sender, EventArgs e )
        {
            Timer timer = new Timer( );
            timer.Interval = 100;
            timer.Tick += ( sender1, e1 ) =>
            {
                userCurve1.AddCurveData( "B", random.Next( 50, 201 ) );
            };
            timer.Start( );
        }
      

如上面的兩個按鈕資訊,必須先點選按鈕4進行曲線初始化,按鈕5的點選才有效果。最終你會看到曲線每隔100ms重新整理一次,不停的有新的資料遞增。

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

當曲線數量超過目前可顯示的點數時,曲線會自動的往左挪動,即時你拉伸的整個控件,它依然可以正常的工作,可顯示的資料點數會自動更新,記憶體中會緩存2048個資料點來支援拉伸的效果轉換。

當然,它也支援一次更新多個資料,雖然這種情況很少,隻是需要注意的是,一次更新的資料必須少于2048。

userCurve1.AddCurveData( "B", new float[] { random.Next( 50, 201 ), random.Next( 50, 201 ), random.Next( 50, 201 ) } );
      

2.2 拉伸模式(請确認 IsAbscissaStrech 為True):

拉伸模式的意思是無論你的data數組有多少個點,都強行按照最大資料點拉伸完整個橫軸界面

先設定 StrechDataCountMax 屬性為 300 ,意思是強行顯示300個點,最大300個點,僅僅在拉伸模式下有效果

private void userButton4_Click( object sender, EventArgs e )
        {
            // 這裡傳入了數組長度為空的資料,不能傳NULL
            userCurve1.SetLeftCurve( "B", new float[] { }, Color.Tomato); // 指定上限500個資料,該上限隻對拉伸模式有效
        }

        private void userButton5_Click( object sender, EventArgs e )
        {
            Timer timer = new Timer( );
            timer.Interval = 100;
            timer.Tick += ( sender1, e1 ) =>
            {
                userCurve1.AddCurveData( "B", random.Next( 50, 201 ) );
            };
            timer.Start( );
        }
      

我們再看拉伸模式的曲線:

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

你再拉伸控件試試看?拉伸模式的意思是無論你的控件多少大小,你規定了300個點,它就是300個點,即使你的控件拉伸了,它還是300個點,隻是沒有那麼密罷了

至于一次增加多個資料是和上面的像素點模式是一緻的。

2.3 模式差別及選擇

像素點模式下,随便看着資料比較密,但是好處在于分辨率高的顯示器,可以顯示的資料更多。

拉伸模式雖然在控件拉伸的情況下顯示的資料量不會增長,但是可以控制疏密程度。

各有優劣,建議先使用像素點模式,看看效果怎麼樣,一般資料變化都是慢慢來的,是以曲線不會像測試資料那樣亂串。如果資料亂串比較厲害,再使用拉伸模式。

3.多曲線,雙坐标使用

多曲線和單曲線模式很相似,無非是多幾條曲線而已,每條曲線的操作,新增資料都是一模一樣的,隻是多曲線的模式都是統一的,要麼全部是像素點模式,要麼全部是拉伸模式,所有的特性和上兩節是相似的。

為了說明使用,舉個例子,你有多個裝置(2個及以上),每個裝置都有一個溫度資訊,現在要進行實時資料的直接對比,當然最好将三條曲線放到一起顯示。

我們命名三個曲線為“A”,“B”,“C” 然後假設所有的資料都是100-200之間,資料A是160-180随機,資料B是150-170随機,資料C是155-165随機

此處測試友善,使用了 像素點模式。在 拉伸模式 下代碼也是一緻的              

我們接下來看一種相當複雜的使用場景,假設我們有一台裝置,需要監控4條曲線,2條溫度,2條壓力,溫度的範圍是0-200,壓力的範圍為0-5 mpa,那麼想要在一個控件裡顯示,也是可以實作的。先調整左右的坐标範圍。

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

此處仍然使用像素點模式,我們接下來寫初始化代碼和新增資料的代碼:

private void userButton4_Click( object sender, EventArgs e )
        {
            userCurve1.SetLeftCurve( "A", new float[] { }, Color.Tomato );            // 溫度1
            userCurve1.SetLeftCurve( "B", new float[] { }, Color.DodgerBlue );        // 溫度2
            userCurve1.SetRightCurve( "C", new float[] { }, Color.LimeGreen );         // 壓力1
            userCurve1.SetRightCurve( "D", new float[] { }, Color.Purple );            // 壓力2
        }

        private void userButton5_Click( object sender, EventArgs e )
        {
            Timer timer = new Timer( );
            timer.Interval = 100;
            timer.Tick += ( sender1, e1 ) =>
            {
                userCurve1.AddCurveData(
                    new string[] { "A", "B", "C", "D" },
                    new float[] { random.Next( 160, 181 ), random.Next( 150, 171 ), (float)random.NextDouble( ) * 2.5f + 1, (float)random.NextDouble( ) * 1f } );
            };
            timer.Start( );
        }
      

效果如下圖:

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

4.橫坐标文本格式調整

上述的實時曲線在顯示的時候,我們看到橫坐标的文本是小時加分鐘的模式,如果我們改成隻顯示分鐘和秒鐘怎麼辦

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

這個屬性就是DateTime的格式化字元串,理論上你可以擷取到任務時間相關的文本資訊,按照目前的需求,調整成 mm:ss 即可

5.輔助線添加

我想在實時資料顯示中設定一條曲線資料的報警上限的輔助線,用來提醒以及更加至關的檢視資訊,是否異常,可以調用控件的方法來完成

新增的輔助線是左右兩個參考坐标系區分出來了,比如我新增左輔助線,192的一條線,顔色為紅色

userCurve1.AddLeftAuxiliary( 192, Color.Red);
      

 移除的代碼為

userCurve1.RemoveAuxiliary( 192 );
      

 輔助線效果如下:

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

如果你新增的輔助線和原有的虛線重疊時,原有的虛線會自動屏蔽掉。

6.背景顔色調整

我修改下背景為暗黑色,瞬間就有黑科技的效果了。當然,線條的顔色可以調整的更加好一點

C# 曲線控件 曲線繪制 實時曲線 多曲線控件 開發

4.結束語

感謝閱讀。