Delphi如何使用基本的繪圖函數繪製統計圖

來源:互聯網
上載者:User

Delphi如何使用基本的繪圖函數繪製統計圖

      一個windows內建的畫圖工具是無論如何也不能滿足我們的畫圖需要的,很多效果都需要我們在另外的工具中來實現。這些進階的功能是如何?的呢,如何操縱一些基本的屬性和函數,讓它們最終能作出我們想要的效果呢?這裡我們以繪製統計圖來說明這些問題。

     解決思路――
     這裡,我們暫且先撇開具體的問題,綜合地一下討論畫圖的問題。
       畫圖工具是基本元素的具體實現,對於我們初學者來說,還是有很好的參考價值的,在delphi 5中有一個內建的工程例子“……Borland\Delphi5\Demos\Doc\Graphex”,這個例子可以實現一些基本的繪圖功能。對這個例子多加修改,一定會有所收穫的。這裡就不列出它的詳細代碼了,有心的讀者可以自己找到這個例子。我這裡只是想綜合地討論這方面的問題。使用DELPHI編寫繪圖軟體的靈魂就在於操作畫布,畫筆和刷子,儘可能地挖掘它們的屬性和相關參數的設定。
     (一)畫布
     畫布,畫筆和刷子之間的關係很明了.其實,畫筆和刷子都是畫布的一個屬性.而畫布也只是TForm,TImage,TShape等組件對象的一個屬性,專門負責與圖象相關的資訊打交道.它的主要作用可以概括如下幾點:
     1.指定使用畫筆,刷子和字型的使用類型;
     2.繪製和填充指定形狀的線或圖形;
     3.修飾和改變圖象;
     畫布的主要屬性有:
     Brush--指定填充圖形和背景的樣式
     CanvasOrientation--指定畫布的定位類型,有coLeftToRight, coRightToLeft兩個屬性;
     ClipRect--指定剪下矩形的邊界;
     CopyMode--指定圖形圖象的複製模式;
     Font--指定畫布上使用的字型;
     Handle--為畫布指定視窗GDI對象的裝置描述表;
     LockCount--指定畫布被別的線程鎖定的次數;
     Pen--指定畫布上使用的畫筆,具體見下面描述;
     PenPos--指定畫筆當前的位置;
     Pixels--指定當前剪下矩形的象素顏色;
     TextFlags--指定字型在畫布上的顯示方式,有ETO_CLIPPED,ETO_OPAQUE,ETO_RTLREADING, ETO_GLYPH_INDEX,ETO_IGNORELANGUAGE,ETO_NUMERICSLOCALETO_NUMERICSLATIN等值可選;
     畫布相關的API函數及其注釋如下:
     Arc--按指定方式畫一條弧;
     BrushCopy--把位元影像複製到指定的畫布的矩形中,用畫布刷子顏色替換位元影像的顏色;
     Chord--按指定方式畫弦;
     CopyRect--從一個矩形地區複製部分圖象到另一個矩形地區;
     Draw--用指定參數在指定位置畫圖;
     DrawFocusRect--按指定焦點風格,通過異或操作來繪製一焦點矩形;
     Ellipse--按指定參數畫一橢圓;
     FillRect--按指定的刷子填充一矩形;
     FloodFill--使用當前選定的刷子填充指定裝置描述表中的一塊地區;
     FrameRect--使用指定的方式畫一矩形的邊框;
     LineTo--使用當前畫筆從當前位置到指定點畫一條直線;
     Lock--防止其它線程在畫布上繪圖;
     MoveTo--指定一新的當前畫筆位置;
     Pie--按指定方式畫餅狀圖;
     PolyBezier--按指定方式畫多條貝塞爾線;
     PolyBezierTo--按指定方式畫多條貝塞爾線並更新當前的畫筆位置值;
     Polygon--繪製一個由多個頂點的任意序列組成 的多邊形;
     Polyline--使用當前畫筆畫一系列的多邊形;
     Rectangle--繪製矩形;
     RoundRect--繪製圓角矩形;
     StretchDraw--在指定的矩形地區通過指定的繪圖參數來繪製圖形;
     TextExtent--返回使用當前字型設定的字元的象素寬度和高度等參數;
     TextHeight--返回使用當前字型設定的字元的象素高度;
     TextOut--在指定位置繪製文本,並更新畫筆的當前位置;
     TextRect--在一剪下矩形地區中繪製文本;
     TextWidth--返回使用當前字型設定的字元的象素寬度;
     TryLock--對當前沒加鎖的畫布進行加鎖;
     Unlock--對當前加鎖的畫布進行解鎖;
     例如以下是兩個小例子:
     procedure TForm1.Button2Click(Sender: TObject);
     var
     ARect: TRect;
     begin //實現了剪下效果;
     with Image1.Canvas do
     begin
     CopyMode := cmWhiteness; //設定複製模式;
     ARect := Rect(0, 0, Image1.Width, Image1.Height);
     CopyRect(ARect, Image1.Canvas, ARect);
     CopyMode := cmSrcCopy; //恢複復制模式;
     end;
     end;
    
     procedure TForm1.Button3Click(Sender: TObject);
     var
     W: Word;
     begin //在視窗中畫一條綵線;
     for W := 10 to 200 do
     Canvas.Pixels[W, 10] :=RGB(random(255),random(255),random(255));;
     end;
     靈活使用這些函數及其內部參數會讓我們得到意想不到的效果;
    
     (二) 畫筆
     畫筆是一個GDI對象,定義了繪製直線或輪廓形狀的方法.
     畫筆內部共有五種屬性:顏色,控制代碼,模式,風格和寬度.
     Color--決定指定直線或輪廓形狀的RGB顏色。
     Handle--指向了視窗畫筆物件控點。
     Mode--指定了畫筆以何種方式在畫布(canvas)上畫線,在協助文檔中的該定義是(全部以pm_開頭):
     type TPenMode =( pmBlack, //總是黑色;
     pmWhite, //總是白色;
     pmNop, //顏色不變;
     pmNot, //畫布顏色取反;
     pmCopy, //顏色屬性中指定的畫筆顏色;
     pmNotCopy, //畫筆顏色取反;
     pmMergePenNot, //畫筆顏色和畫布背景色取反後顏色的結合;
     pmMaskPenNot, //畫筆顏色和畫筆背景色取反後顏色共同色的結合;
     pmMergeNotPen, //畫筆顏色取反後和畫布背景色的結合;
     pmMaskNotPen, //畫布顏色和畫筆顏色取反後顏色共同色的結合;
     pmMerge, //畫筆和畫布背景色的結合;
     pmNotMerge, //畫筆顏色和畫布背景色的結合;
     pmMask, //畫筆和畫布背景色共同色的結合;
     pmNotMask, //pmMask取反,畫筆和畫布背景色共同色的結合;
     pmXor, //取畫筆或畫布背景中的任一種顏色;
     pmNotXor //pmXor取反,取畫筆或畫布背景中的任一種顏色;
     );
     Style--則指定了畫筆操作的風格,線上文檔中的定義是(全部以ps_開頭):
     type TPenStyle=( psSolid, //畫筆是───
     psDash, //畫筆是------
     psDot, //畫筆是......
     psDashDot, //畫筆是_._._.
     psDashDotDot, //畫筆是_.._..
     psClear, //畫筆是透明色
     psInsideFrame //畫筆是實線,但設定大於1時會抖動;
     );
     另外,在windows.pas中還有其他擴充的畫筆風格定義,只在特殊的支援裝置上
     才有效,如PS_ENDCAP_ROUND, PS_JOIN_ROUND等;
     Width--指定了待使用畫筆的寬度,單位是象素.
     和畫筆相關的函數有:
     CreatePen--用指定風格建立畫筆;
     CreatePenIndirect--根據LOGPEN資料結構建立一畫筆;
     ExtCreatePen-- 建立帶指定風格,寬度和刷子屬性的幾何畫筆;
    
     (三)刷子
     刷子定義了地區填充的GDI對象,刷子是一個8×8象素的地區,它可以被繪製在指定的設
     備上.刷子不僅可以是純色的,也可以由不同的位元影像圖案組成.
     刷子的屬性有位元影像,顏色,控制代碼和風格四種:
     Bitmap--是指定一個外部位元影像檔案來填充指定的地區.如果指定的圖象比填充的地區大,
     則只有左上方與填充地區等大的部分有效,其餘的被自動裁減了.
     Color--指定了刷子的顏色.當刷子風格為bsClear時,該屬性無效.
     Handle--指向指定裝置視窗.
     Style--則指定了當前刷子的填充風格,線上文檔中的定義是(都以bs_開頭):
     type TBrushStyle=( bsSolid, //填充格式為實體填充
     bsClear, //填充格式為透明填充
     bsHorizontal, //填充格式為------
     bsVertical, // 填充格式為|||||
     bsFDiagonal, // 填充格式為/////
     bsBDiagonal, // 填充格式為\\\\\
     bsCross, // 填充格式為+++++
     bsDiagCross // 填充格式為xxxxx
    
     );
     和刷子有關的API函數有:
     CreateBrushIndirect--根據LOGBRUSH建立一刷子;
     CreateDIBPatternBrushPt--使用裝置無關位元影像來建立刷子,以便指定刷子的模式;
     CreateHatchBrush--建立一帶有陰影模式的刷子,陰影模式為以HS_開頭的常數;
     CreatePatternBrush--用位元影像來建立刷子,以便指定刷子的模式;
     CreateSolidBrush--建立一實體顏色刷子;
     GetBrushOrgEx--擷取指定裝置描述表中當前選擇刷子的原點;
     GetSysColorBrush--擷取和指定色彩索引相關的邏輯刷子的控制代碼;
     SetBrushOrgEx--設定指定裝置描述表中當前選擇刷子的原點;
    
     (四)畫圖和填充相關的API函數;
     BeginPaint--準備在指定視窗繪畫或對指定地區進行填充;
     DrawAnimatedRects--NT支援函數,畫一環有遊動邊框的矩形;
     DrawCaption--NT支援函數,為指定視窗的標題賦值;
     DrawEdge--為指定矩形畫一道或多道邊框;
     DrawFocusRect--畫焦點矩形;
     DrawFrameControl--畫一指定類型和風格的邊框控制項;
     DrawState--NT支援函數,為圖象畫一可視效果標明其狀態;
     DrawStateProc--NT支援函數,調用為圖象畫一可視效果標明其狀態的函數;
     DrawTextEx--NT支援函數,在指定地區輸出格式化文本;
     EndPaint--結束繪畫;
     ExcludeUpdateRgn--將視窗無效部分(更新地區)從裁剪區中排除掉;
     GdiFlush--使當前GDI閃爍;
     GdiGetBatchLimit--擷取緩衝GDI函數數量;
     GdiSetBatchLimit--設定緩衝GDI函數數量;
     GetBkColor--擷取背景顏色;
     GetBkMode--擷取背景模式;
     GetBoundsRect--擷取邊界矩形;
     GetROP2--擷取當前繪圖模式;
     GetUpdateRect--擷取指定視窗最小的矩形;
     GetUpdateRgn--擷取描述視窗中無效區的地區;
     GetWindowDC--擷取視窗DC;
     GetWindowRgn--擷取視窗地區;
     GrayString--在指定位置畫灰色文本;
     InvalidateRect--使DC指定的矩形無效;
     InvalidateRgn--使DC指定的矩形無效;
     LockWindowUpdate--禁止或允許在指定視窗中繪畫;
     OutputProc--調用輸出進程,向GrayString輸送文本;
     PaintDesktop--NT支援函數,在指定的視窗地區用指定的案頭顏色或牆紙填充裁剪區;
     RedrawWindow--更新客戶區的指定地區或矩形;
     SetBkColor--設定背景顏色;
     SetBkMode--設定背景模式;
     SetBoundsRect--設定邊界矩形;
     SetRectRgn--設定矩形地區;
     SetROP2--設定當前繪圖模式;
     SetWindowRgn--設定視窗地區;
     UpdateWindow--更新視窗;
     ValidateRect--使客戶區中指定矩形有效;
     ValidateRgn--使客戶區中的指定地區有效;
     WindowFromDC--擷取和指定視窗相關的控制代碼;
    
     具體實現――
     1.本例以常見的統計圖來說明問題。該例能實現對統計圖的動態繪製,並且可以自訂設定統計圖的形狀和顏色。在說明問題之前,來瞭解程式用到的一些比較複雜的函數或演算法:
     函數――
     1.Polygon(Points: array of TPoint)
     用於繪出指定的多邊形。括弧內是預定點的集合,該集合可以在使用之前定義,也可以在使用時同時定義,本例屬於後者;
     2.Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Longint)
     用於繪製餅狀圖,餅狀圖其實就是橢圓的一部分。在這些參數中,其中(X1, Y1)和(X2, Y2)定義了框住餅狀圖的矩形,而從橢圓中心發出的射線經過(X3, Y3)和(X4, Y4)兩點,就把一個餅狀圖截出來了。
     3.FormatFloat(const Format: string; Value: Extended)
     函數的意義是按指定方式格式化字串,Format指定了格式化的方式,Value則指定了要格式化的文本或其他資料。下面列舉了一些範例,可供我們學習時參考:
     格式化符號(Format) 1234 -1234 0.5 0
     1234 -1234 0.5 0
     0 1234 -1234 1 0
     0.00 1234.00 -1234.00 0.50 0.00
     #.## 1234 -1234 .5
     #,##0.00 1,234.00 -1,234.00 0.50 0.00
     #,##0.00;(#,##0.00) 1,234.00 (1,234.00) 0.50 0.00
     #,##0.00;;Zero 1,234.00 -1,234.00 0.50 Zero
     0.000E+00 1.234E+03 -1.234E+03 5.000E-01 0.000E+00
     #.###E-0 1.234E3 -1.234E3 5E-1 0E0
     該例是在小數點後保留兩位小數,因此用"##.##",具體見程式碼中。
    
     演算法――
     本例的實現依賴一定的演算法。這裡介紹主要的兩點:
     1)在串連多邊形各點時,我們要注意那幾個點一定要構成一個閉合的圖形,這就要保證最後一個點要和第一個點重合。至於其他的點怎麼布局,則要有一定的空間感。
     我們先畫一個矩形,然後再根據平行關係確定其他的點:
     rectangle(50,x,70,220); //畫主視面;
     Canvas.Polygon([Point(50, x), Point(70,x-10),Point(90,x-10), Point(70, x),Point(50, x)]);  //畫頂面;
     Canvas.Polygon([Point(90,x-10), Point(70, x),Point(70,220),Point(90,210),Point(90,x-10)]); //畫側面;
    
     2)確定圓上指定角度的邊與圓的交點
     在該例中畫餅狀圖時,我們要按照一定的比例畫扇形,這就要確定扇形的起始點和終止點。我們把起始點設為一個定點,而終止點則根據實際情況設定,
    
     ――餅狀圖的數學原理――
    
     假設畫圖時已知一個比例數是K,則在餅狀圖中的角度是θ=(K*360),根據圖中的關係(Y軸向下符合螢幕座標系定義),可以用三角函數知識求得PX,PY:
     PX=op*cosθ
     PY=op*sinθ
     上述式子的前提條件是O點是原點,OP是圓的半徑。如果O點不是原點,而是座標系中的一個點(X0,Y0),則此時的P點座標是
     PX=X0+op*cosθ
     PY=Y0+op*sinθ
    
     3.本例的介面布局可以參考程式啟動並執行結果圖,其中代表“刷子類型”的combobox1的items的屬性設定。該例實現的主要代碼如下:
     procedure TForm1.Button1Click(Sender: TObject);
     var
     x,i,j:integer;
     k:real;
     begin
     refresh;
     //標明寫上“Y”軸;
     label4.left:=25;
     label4.top:=2;
     label4.caption:='Y';
     label4.Transparent:=true;
     //標明寫上“X”軸;
     label5.left:=395;
     label5.top:=227;
     label5.caption:='X';
     label5.Transparent:=true;
     x:=220-round(strtofloat(edit1.text)/strtofloat(edit2.text)*200);
    
     with form1.Canvas do
     begin
     pen.width:=strtoint(edit3.text); //設定畫筆寬度;
     case combobox1.Items.IndexOf(combobox1.text) of //設定刷子的填充風格;
     0: brush.style:=bsSolid;
     1: brush.style:=bsClear;
     2: brush.style:=bsHorizontal;
     3: brush.style:=bsVertical;
     4: brush.style:=bsFDiagonal;
     5: brush.style:=bsBDiagonal;
     6: brush.style:=bsCross;
     7: brush.style:=bsDiagCross;
     end;
     //畫出X軸;
     MoveTo(2,220);
     LineTo(400,220);
     //畫出Y軸;
     MoveTo(20,5);
     LineTo(20,230);
     //畫出Y軸的箭頭方向"∧";
     moveto(20,5);
     lineto(15,12);
     moveto(20,5);
     lineto(25,12);
     //畫出X軸的箭頭方向"∧";
     moveto(400,220);
     lineto(395,213);
     moveto(400,220);
     lineto(395,227);
     if checkbox1.Checked then //繪製立體的直方柱圖;
     begin
     //畫正面的矩形圖;,可以根據實際情況動態定義它的高度;
     rectangle(50,x,70,220);
     //畫頂面,隨著正面矩形的高度變化而變化;
     Canvas.Polygon([Point(50, x), Point(70,x-10),Point(90,x-10), Point(70, x),Point(50, x)]);
     //畫側面,隨著正面矩形的高度變化而變化;
     Canvas.Polygon([Point(90,x-10), Point(70, x),Point(70,220),Point(90,210),Point(90,x-10)]);
     end
     else
     rectangle(50,x,70,220); //如果沒有選中要以立體形式繪製,則以平面形式繪製的直方柱圖;
     //畫餅狀統計圖
     k:=(strtofloat(edit1.text)/strtofloat(edit2.text))*360; //將資料按比例轉換成;
     i:=round(250+100*cos(k*3.14159/180));
     j:=round(120+100*sin(k*3.14159/180));
     pie(150,20,350,220,i,j,350,120);
     label3.caption:='比例是'+formatfloat('##.##',(k/360)*100)+'%'; //設定比例的函數;
     end;
     end;
     procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
     begin
     if colordialog1.Execute then //設定視窗背景顏色;
     shape1.Brush.color:=colordialog1.Color;
     form1.color:=ColorDialog1.Color;
     end;
    
     procedure TForm1.Shape2MouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
     begin
     if colordialog2.Execute then //設定刷子顏色;
     shape2.Brush.color:=colordialog2.Color;
     form1.Canvas.Brush.color:=colordialog2.Color;
     end;
    
     procedure TForm1.Shape3MouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
     begin
     if colordialog3.Execute then //設定畫筆顏色;
     shape3.Brush.color:=colordialog3.Color;
     form1.Canvas.Pen.color:=colordialog3.Color;
     end;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.