C# 歷史曲線控件 基於時間的曲線控件 可交互的高級曲線控件 HslControls曲線控件使用教程

本篇博客主要對 HslControls 中的曲線控件作一個詳細的教程說明,你們能夠根據下面的教程開發出高質量的曲線控件html

 

Prepare


先從nuget下載到組件,而後就可使用組件裏的各類組件信息了。git

 

在Visual Studio 中的NuGet管理器中能夠下載安裝,也能夠直接在NuGet控制檯輸入下面的指令安裝:github

Install-Package HslControls

  

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

Demo


 

demo項目的源代碼,https://github.com/dathlin/HslControlsDemodom

有一個demo程序能夠下載,地址爲 demo.zipspa

所支持的控件信息以下:設計

pic1

曲線控件先上圖,看看3d

pic2

 

 

適用場景


 

正式開始文章以前,咱們先來看看這個曲線控件到底爲了解決什麼樣子的問題的,在工業的場景中,咱們會採集一些設備的工藝參數信息,好比鍋爐和模具溫度,鍋爐壓力,倉庫溼度,等等狀況的信息,咱們會在數據庫創建一張數據表,可能2秒鐘存儲一條數據,可能5秒鐘存儲一條數據等等,甚至可能30秒,如今咱們有數據了,須要將數據進行顯示出來,使用本控件便可以快速的開發可交互式的曲線顯示。orm

以下就是一個數據庫的示例htm

 

曲線顯示


 固然實際中你能夠根據本身的狀況來,不過這都無所謂,應該本控件是須要傳入處理過的數據的,ok,咱們如今界面上拖一個控件

 

先調整兩側座標軸的,好比溫度的範圍是0-250,壓力的範圍是0-5,咱們就調整這個控件的屬性來實現功能

還能夠調整分割線的狀況,咱們調整成以下的數據

而後顯示以下:

 

 咱們再調整下文字,設置爲空,在新增一個按鈕,點擊的時候就要去數據庫查詢數據了,因爲查詢的時間不定,須要花費一些時間,咱們還須要進行友好的提示信息,好比正在查詢數據...

 

而後咱們完善代碼

        private void button1_Click( object sender, EventArgs e )
        {
            hslCurveHistory1.Text = "正在加載數據...";
            hslCurveHistory1.RemoveAllCurve( );
            new Thread( new ThreadStart( ThreadReadExample1 ) ) { IsBackground = true }.Start( );
        }

        private void ThreadReadExample1( )
        {
            // 模擬下查詢時間
            Thread.Sleep( 2000 );
           
            // 這裏數據數據,實際應該是你的真實的數據
            float[] temp = new float[2000];
            for (int i = 0; i < temp.Length; i++)
            {
                temp[i] = Convert.ToSingle( random.NextDouble( ) * 40 + 100 );
            }

            // 顯示出數據信息來
            Invoke( new Action( ( ) =>
            {
                // 設置曲線屬性,名稱,數據,顏色,是否平滑,格式化顯示文本
                hslCurveHistory1.SetLeftCurve( "溫度", temp, Color.DodgerBlue, true, "{0:F1} ℃" );
                hslCurveHistory1.RenderCurveUI( );
            } ) );
        }

        private Random random = new Random( );

此處只有一條曲線,橫軸還沒設置,這已是最簡單的曲線顯示了,並且支持按鈕屢次重複點擊,不會發生數據疊加。效果以下:

 

當光標移動的時候,還會提示當前的光標所在位置的數據信息,目前所具有的功能仍是比較簡單的,咱們從數據庫獲取到數據,一般還包含了時間軸,此處就要傳入同等數量長度的時間軸信息

注意,時間軸是隨着時間逐漸增長的信息,確保是單向增長的。

因此咱們的代碼改爲以下:

        private void ThreadReadExample1( )
        {
            // 模擬下查詢時間
            Thread.Sleep( 2000 );
           
            // 這裏數據數據,實際應該是你的真實的數據
            float[] temp = new float[2000];
            DateTime[] times = new DateTime[2000];
            for (int i = 0; i < temp.Length; i++)
            {
                temp[i] = Convert.ToSingle( random.NextDouble( ) * 40 + 100 );
                times[i] = DateTime.Now.AddSeconds( i - 2000 );
            }

            // 顯示出數據信息來
            Invoke( new Action( ( ) =>
            {
                // 設置曲線屬性,名稱,數據,顏色,是否平滑,格式化顯示文本
                hslCurveHistory1.SetLeftCurve( "溫度", temp, Color.DodgerBlue, true, "{0:F1} ℃" );
                hslCurveHistory1.SetDateTimes( times );
                hslCurveHistory1.RenderCurveUI( );// 全部的曲線設置好後,調用這個方法統一顯示曲線信息,這樣的設計能夠有效的避免閃爍的問題
            } ) );
        }

  

這時候的效果已經改變了。最下面已經多了一個時間的信息顯示。

這時候咱們在圖形的任意區域點擊鼠標左鍵,而後移動鼠標,而後再鬆開鼠標左鍵就會發生填充輔助曲線信息

 

這時候能夠屢次的重複操做,能夠標記多個圖形信息。

若是想要清除上面的全部的數據信息,怎麼辦?右鍵點擊下圖形的任意界面,全部的輔助曲線就不存在了。

 

 

接下來咱們再增長一條曲線,壓力相關的,再看看效果。

        private void ThreadReadExample1( )
        {
            // 模擬下查詢時間
            Thread.Sleep( 2000 );
           
            // 這裏數據數據,實際應該是你的真實的數據
            float[] temp = new float[2000];
            float[] press = new float[2000];
            DateTime[] times = new DateTime[2000];
            for (int i = 0; i < temp.Length; i++)
            {
                temp[i] = Convert.ToSingle( random.NextDouble( ) * 40 + 100 );
                press[i] = Convert.ToSingle( random.NextDouble( ) * 0.5d + 4 );
                times[i] = DateTime.Now.AddSeconds( i - 2000 );
            }

            // 顯示出數據信息來
            Invoke( new Action( ( ) =>
            {
                // 設置曲線屬性,名稱,數據,顏色,是否平滑,格式化顯示文本
                hslCurveHistory1.SetLeftCurve( "溫度", temp, Color.DodgerBlue, true, "{0:F1} ℃" );
                hslCurveHistory1.SetRightCurve( "壓力", press, Color.Tomato, true, "{0:F2} Mpa" );
                hslCurveHistory1.SetDateTimes( times );
                hslCurveHistory1.RenderCurveUI( );
            } ) );
        }

效果以下:

 

假設我還有個步序的信息,只想在曲線裏提示出來,可是不想顯示步序曲線,應該怎麼操做呢

        private void ThreadReadExample1( )
        {
            // 模擬下查詢時間
            Thread.Sleep( 2000 );
           
            // 這裏數據數據,實際應該是你的真實的數據
            float[] temp = new float[2000];
            float[] press = new float[2000];
            float[] steps = new float[2000];
            DateTime[] times = new DateTime[2000];
            for (int i = 0; i < temp.Length; i++)
            {
                temp[i] = Convert.ToSingle( random.NextDouble( ) * 40 + 100 );
                press[i] = Convert.ToSingle( random.NextDouble( ) * 0.5d + 4 );
                times[i] = DateTime.Now.AddSeconds( i - 2000 );
            }

            // 顯示出數據信息來
            Invoke( new Action( ( ) =>
            {
                // 設置曲線屬性,名稱,數據,顏色,是否平滑,格式化顯示文本
                hslCurveHistory1.SetLeftCurve( "溫度", temp, Color.DodgerBlue, true, "{0:F1} ℃" );
                hslCurveHistory1.SetRightCurve( "壓力", press, Color.Tomato, true, "{0:F2} Mpa" );
                hslCurveHistory1.SetDateTimes( times );
                hslCurveHistory1.SetLeftCurve( "步序", steps );
                hslCurveHistory1.SetCurveVisible( "步序", false );         // 不顯示曲線信息
                hslCurveHistory1.RenderCurveUI( );
            } ) );
        }

  

這樣以後咱們就能夠顯示步序的提示信息,可是不顯示步序的曲線。

這裏有個小問題,若是我但願步序顯示順序在最上面怎麼辦?或者是這裏的提示信息是根據什麼順序來排序的?

答案是曲線的添加順序,咱們只須要調整曲線添加的順序便可。以下:

                // 設置曲線屬性,名稱,數據,顏色,是否平滑,格式化顯示文本
                hslCurveHistory1.SetLeftCurve( "步序", steps );
                hslCurveHistory1.SetLeftCurve( "溫度", temp, Color.DodgerBlue, true, "{0:F1} ℃" );
                hslCurveHistory1.SetRightCurve( "壓力", press, Color.Tomato, true, "{0:F2} Mpa" );
                hslCurveHistory1.SetDateTimes( times );
                hslCurveHistory1.SetCurveVisible( "步序", false );         // 不顯示曲線信息
                hslCurveHistory1.RenderCurveUI( );

  

 

 

到這裏爲止,曲線控件的簡單應用已經差很少了,已經實現了通常的狀況的應用了。接下來就是比較高級的操做了。

 

高級操做


 

 

 在高級的操做以前,須要先普及個概念,貫穿於這個曲線控件的全部的部分。這個概念就是數據點位的信息,好比咱們有2000個數據,那麼數據點位就是0-1999,在圖形上顯示不必定是0-1999的位置,存在一個縮放的等級,默認縮放等級是1,也就是說0-1999就是0-1999,若是咱們的縮放等級調整爲2,那麼就是放大,0-1999對應 0-3998,若是縮放等級爲0.5,那麼就是縮小一倍,0-1999對應0-999

 

單位顯示


 

顯示單位的信息

這樣就能夠在圖形裏顯示

 

 

隱藏右座標


 

若是咱們想要隱藏右座標軸信息,能夠設置下面的屬性

 

將這個值設置爲 False 後,就不顯示右座標了,以下:

 

 

 

輔助線功能

若是咱們須要標記一段特殊的虛線,能夠是報警的分界線,也能夠是重點的線。操做以下:在窗體的載入中添加以下的代碼便可

        private void FormCurveDemo_Load( object sender, EventArgs e )
        {
            hslCurveHistory1.AddLeftAuxiliary( 172f );
        }

  

效果以下:

 

固然咱們也能夠指定顏色

        private void FormCurveDemo_Load( object sender, EventArgs e )
        {
            hslCurveHistory1.AddLeftAuxiliary( 172f, Color.Yellow );
        }

  

 

 固然也能夠添加右曲線信息

 

縮放功能


 

若是你以爲目前的數據點位太多了,曲線太長了,能夠進行縮小,那麼能夠設置縮放等級,在窗口載入的時候設置一次便可。

 

        private void FormCurveDemo_Load( object sender, EventArgs e )
        {
            hslCurveHistory1.AddLeftAuxiliary( 172f, Color.Yellow );
            hslCurveHistory1.SetScaleByXAxis( 0.5f );
        }

  

 

 

 接下來咱們看看縮放等級設置爲4的效果

 

        private void FormCurveDemo_Load( object sender, EventArgs e )
        {
            hslCurveHistory1.AddLeftAuxiliary( 172f, Color.Yellow );
            hslCurveHistory1.SetScaleByXAxis( 4f );
        }

  

 

 

 

 

數據點標註操做


 

 咱們如今有個需求,咱們有了曲線之後,可能對其中的某個或是多個特殊的點進行文本標註,本控件支持這樣的操做,以及標註不一樣的顏色的信息

hslCurveHistory1.AddMarkText( new HslControls.HslMarkText( )
                {
                    Index = 200,
                    CurveKey = "溫度",
                    MarkText = "標註信息",
                    CircleBrush = Brushes.DodgerBlue,
                    TextBrush = Brushes.Blue
                } );
                hslCurveHistory1.RenderCurveUI( );

固然也能夠指定文本的方向,若是想要清除,那麼調用

            hslCurveHistory1.RemoveAllMarkText( );
            hslCurveHistory1.RenderCurveUI( );

  

 

 

 

數據線標註操做


 咱們如今又有個需求,須要對曲線裏的一個區域畫線標註出來。而且能夠再標註點信息

                 // 增長一個三角形的線段標記示例 Points的每一個點的X是數據索引,Y是數據值(須要選對參考座標軸,默認爲左座標軸)
                 hslCurveHistory1.AddMarkLine( new HslControls.HslMarkLine( )
                 {
                     CircleBrush = Brushes.DodgerBlue,
                     IsLeftFrame = true,
                     IsLineClosed = true,
                     LinePen = Pens.DodgerBlue,
                     TextBrush = Brushes.DodgerBlue,
                     Points = new PointF[]
                     {
                         new PointF(200, 180f), new PointF(260, 20f), new PointF(550, 150f),
                     },
                     Marks = new string[] { "AA", "BB", "CC" },
                 } );

效果以下:

 

 

 

背景標識操做


 

 咱們如今有個需求,咱們有了步序以後就能夠分析出曲線對應的產品信息,好比分析出點位是從1000點開始到1300點結束的,是一個產品,條碼是 K1234567890 ,如今要在曲線裏顯示出來。咱們來看看若是經過代碼實現

 咱們先調整爲正常的縮放等級,也就是1f,

        private void ThreadReadExample1( )
        {
            // 模擬下查詢時間
            Thread.Sleep( 2000 );
           
            // 這裏數據數據,實際應該是你的真實的數據
            float[] temp = new float[2000];
            float[] press = new float[2000];
            float[] steps = new float[2000];
            DateTime[] times = new DateTime[2000];
            for (int i = 0; i < temp.Length; i++)
            {
                temp[i] = Convert.ToSingle( random.NextDouble( ) * 40 + 100 );
                press[i] = Convert.ToSingle( random.NextDouble( ) * 0.5d + 4 );
                times[i] = DateTime.Now.AddSeconds( i - 2000 );
            }

            // 顯示出數據信息來
            Invoke( new Action( ( ) =>
            {
                // 設置曲線屬性,名稱,數據,顏色,是否平滑,格式化顯示文本
                hslCurveHistory1.SetLeftCurve( "步序", steps );
                hslCurveHistory1.SetLeftCurve( "溫度", temp, Color.DodgerBlue, true, "{0:F1} ℃" );
                hslCurveHistory1.SetRightCurve( "壓力", press, Color.Tomato, true, "{0:F2} Mpa" );
                hslCurveHistory1.SetDateTimes( times );
                hslCurveHistory1.SetCurveVisible( "步序", false );         // 不顯示曲線信息


                HslControls.HslMarkBackSection backSection = new HslControls.HslMarkBackSection( )
                {
                    StartIndex = 1000,
                    EndIndex = 1300,
                    MarkText = "K1234567890",
                };
                hslCurveHistory1.AddMarkBackSection( backSection );


                hslCurveHistory1.RenderCurveUI( );
            } ) );
        }

        private Random random = new Random( );

        private void FormCurveDemo_Load( object sender, EventArgs e )
        {
            hslCurveHistory1.AddLeftAuxiliary( 172f, Color.Yellow );
        }

  

代碼上來講,就是新增一個 backSection 對象,至於1000和1300怎麼分析出來的,就是要本身寫代碼實現了,簡單的說,經過遍歷數據,先後對比能夠實現。運行效果以下:

 

能夠清楚的看到有一個顏色稍微淡一點點的標記層,若是你的縮放等級是0.5,那麼這個陰影的寬度會減小一半,這都是自動適應的。

固然你也能夠添加多個背景的標記,若是想要清除標記,只能調用清除全部曲線的方法,

以下是縮放等級爲0.5的狀況

 

 

區間標識操做


 咱們如今有另外的需求,須要標記某些特殊的區間,好比某個區間發生了報警,例如區間 600-700發生了報警,內容爲「溫度超標了」;應該怎麼操做

        private void ThreadReadExample1( )
        {
            // 模擬下查詢時間
            Thread.Sleep( 2000 );
           
            // 這裏數據數據,實際應該是你的真實的數據
            float[] temp = new float[2000];
            float[] press = new float[2000];
            float[] steps = new float[2000];
            DateTime[] times = new DateTime[2000];
            for (int i = 0; i < temp.Length; i++)
            {
                temp[i] = Convert.ToSingle( random.NextDouble( ) * 40 + 100 );
                press[i] = Convert.ToSingle( random.NextDouble( ) * 0.5d + 4 );
                times[i] = DateTime.Now.AddSeconds( i - 2000 );
            }

            // 顯示出數據信息來
            Invoke( new Action( ( ) =>
            {
                // 設置曲線屬性,名稱,數據,顏色,是否平滑,格式化顯示文本
                hslCurveHistory1.SetLeftCurve( "步序", steps );
                hslCurveHistory1.SetLeftCurve( "溫度", temp, Color.DodgerBlue, true, "{0:F1} ℃" );
                hslCurveHistory1.SetRightCurve( "壓力", press, Color.Tomato, true, "{0:F2} Mpa" );
                hslCurveHistory1.SetDateTimes( times );
                hslCurveHistory1.SetCurveVisible( "步序", false );         // 不顯示曲線信息


                HslControls.HslMarkBackSection backSection = new HslControls.HslMarkBackSection( )
                {
                    StartIndex = 1000,
                    EndIndex = 1300,
                    MarkText = "K1234567890",
                };
                hslCurveHistory1.AddMarkBackSection( backSection );

                HslControls.HslMarkForeSection foreSection = new HslControls.HslMarkForeSection( )
                {
                    StartIndex = 600,
                    EndIndex = 800,
                    StartHeight = 0.3f,         // 若是值是(0-1)的話,表示的是位置百分比,0.9就是曲線高度爲90%,從上往下看的視角,若是填了600,那就是絕對座標
                    Height = 0.9f,              // 和上面同理
                    LinePen = Pens.Chocolate,   // 指定顏色
                    IsRenderTimeText = false,   // 是否顯示額外的起始時間和結束時間,此處就不要了
                    MarkText = "溫度超標了",
                };
                hslCurveHistory1.AddMarkForeSection( foreSection );

                hslCurveHistory1.RenderCurveUI( );  // 將曲線顯示出來
            } ) );
        }

  

  如上圖,咱們完成了標記信息的添加,上述 的幾個屬性,你能夠修改試試看,而後運行看看效果。上述的效果以下:

 

固然了,文字的顏色也能夠設定的,用於不一樣功能的區段的提醒,這個區段也是支持自動的縮放的。

 

 

雙擊曲線操做


若是你想捕獲鼠標雙擊曲線的事件,獲取到數據的索引或是實際的時間信息,好進行一些額外的操做,好比打印雙擊時間附近的曲線,生成報告單之類的狀況,就顯得頗有用了。那麼應該怎麼作呢?

在這個事件裏雙擊生成事件便可。

        private void hslCurveHistory1_onCurveDoubleClick( HslControls.HslCurveHistory hslCurve, int index, DateTime dateTime )
        {
            MessageBox.Show( $"Index: {index} Time:{dateTime.ToString( )}" );
        }

天然會生成上述的代碼,其中index就是數據索引,和圖形的縮放是自動適應的,還有時間信息,也是能夠一併獲取到的,能夠進行額外的處理。

 

兩個曲線控件同步操做


若是你有個需求。有兩個曲線控件,時間軸是如出一轍的,想要鼠標挪動的時候,讓另外一個曲線也跟着動,或是互相一塊兒動,再或是是光標也實現一塊兒運動,這東西解釋起來比較複雜,先上效果圖:

 

首先我先放兩個控件,曲線1和曲線2,若是想讓曲線2跟隨曲線1移動

hslCurveHistory1.Scroll += (sender1 , e1) => hslCurveHistory2.SetScrollPosition( e1 );

若是想要實現互相跟隨

hslCurveHistory1.Scroll += (sender1 , e1) => hslCurveHistory2.SetScrollPosition( e1 );
hslCurveHistory2.Scroll += ( sender1, e1 ) => hslCurveHistory1.SetScrollPosition( e1 );

  

光標移動也是同理,互相移動參考以下:

hslCurveHistory1.onCurveMouseMove += ( curve, x, y ) => hslCurveHistory2.SetCurveMousePosition( x, y );
hslCurveHistory2.onCurveMouseMove += ( curve, x, y ) => hslCurveHistory1.SetCurveMousePosition( x, y );

  

 

 

主題調整操做


 

固然,你不喜歡暗色主題的話,經過調整全部的顏色配置,來達到亮色的主題的話,以下的配置只是一個示例

配色的結果以下:

pic100

 

 

 

好了,更詳細的就參考demo項目的源代碼,https://github.com/dathlin/HslControlsDemo

相關文章
相關標籤/搜索