小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

WinForm 畫個時鐘

 XXG學(xué)習(xí)園 2012-04-07

今天學(xué)習(xí)GDI+,試著想寫一個模擬時鐘的小程序,原以為很簡單實現(xiàn);但其實還有些復(fù)雜,特別是利用三角函數(shù)的那部分,讓我四處找資料惡補了一下高中數(shù)學(xué)才算弄清楚,現(xiàn)在就回顧一下這個程序吧.

程序的目的是要模擬出時鐘的效果,那首先就是要畫出這個時鐘的樣子。不考慮美觀,一個時鐘最簡單的組成是一個圓形的表盤,三根直線代表的時針、分針和秒針。

 

看起來很簡單吧,但要怎么樣畫呢?讓我們一步一步來吧:

1.畫表盤

Graphics g = this.CreateGraphics(); //創(chuàng)建一個Graphics對象

Pen myPen = new Pen(Color.Blue,1); //創(chuàng)建一個自定義畫筆對象

//創(chuàng)建一個正方形rect
int myRect_X = this.ClientRectangle.Right/4;
int myRect_Y = this.ClientRectangle.Bottom/4;
int myRect_Width;
int myRect_Height;
if(this.ClientRectangle.Height< this.ClientRectangle.Width)
{

myRect_Width = this.ClientRectangle.Height/2;
myRect_Height = this.ClientRectangle.Height/2;
}
else
{
myRect_Width = this.ClientRectangle.Width/2;
myRect_Height = this.ClientRectangle.Width/2;
}


Rectangle rect = new Rectangle(myRect_X,myRect_Y,myRect_Width,myRect_Height);

g.DrawEllipse(myPen,rect); //畫出一個內(nèi)切于矩形rect的圓

 


Graphics.DrawEllipse方法有幾種重載方式,其中較常用的就是Graphics.DrawEllipse(Pen,Rectangle),這個重載方法需要提供一個Rectangle參數(shù),然后根據(jù)這個矩形的形狀內(nèi)切出橢圓,若這個矩形是正方形,則切出來的是一個正圓.

這段程序最關(guān)鍵的地方就在于得到這個矩形了,因為它間接決定了表盤的位置與大小,Rectangle的構(gòu)造函數(shù)需要四個參數(shù),矩形左上角的X、Y坐標(biāo),寬度與高度.

這里的ClientRectangle所代表的是控件的工作區(qū),它也是一個Rectangle類型的對象,是指控件的邊界減去非工作區(qū)元素(如滾動條、邊框、標(biāo)題欄和菜單)。相應(yīng)的Right,Bottom,Width,Height分別代表了右邊緣的X坐標(biāo),下邊緣的Y坐標(biāo),寬度與高度.

為了使這個表盤適應(yīng)窗口的變化,這里將這些值全部設(shè)置為相對與ClientRectangle相關(guān)屬性的值,如下圖:

 

這樣當(dāng)窗口大小變化時,這個圓的外切矩形也隨之改變,假如這個窗口的寬度比高度大太多,或反之,則可能會出現(xiàn)表盤的部分超出工作區(qū)域無法顯示,為了防止這種情況,加入了條件判斷語句。如果寬度大于高度,則圓的直徑取高度值;反之則取寬度值。當(dāng)然高度等于寬度時,圓是在工作區(qū)域正中間。

2.畫表針

將表盤畫好后,就可以開始畫表針了,這也是最復(fù)雜的一步

//得到中心點坐標(biāo)
int centerPoint_X = rect.Right - rect.Width/2;
int centerPoint_Y = rect.Bottom - rect.Height/2;
Point centerPoint = new Point(centerPoint_X,centerPoint_Y);

int s_Len = rect.Width*0.45; //秒針長度
int m_Len = rect.Width*0.35//分針長度
int l_Len = rect.Width*0.25 //時針長度

//得到當(dāng)前時間
int h = DateTime.Now.Hour;
int m = DateTime.Now.Minute;
int s = DateTime.Now.Second;

//得到秒針頂點坐標(biāo)
int sec_X = (int)(centerPoint.X + Math.Sin(6*Math.PI/180*s)*s_Len);
int sec_Y = (int)(centerPoint.Y - Math.Cos(6*Math.PI/180*s)*s_Len);
Point secPoint = new Point(sec_X,sec_Y);

//得到分針頂點坐標(biāo)
int min_X = (int)(centerPoint.X + Math.Sin(6*Math.PI/180*m)*m_Len);
int min_Y = (int)(centerPoint.Y - Math.Cos(6*Math.PI/180*m)*m_Len);
Point minPoint = new Point(min_X,min_Y);

//得到時針頂點坐標(biāo)
int hour_X = (int)(centerPoint.X + Math.Sin(h*30+m/2)*Math.PI/180*h_Len);
int hour_Y = (int)(centerPoint.Y - Math.Cos(h*30+m/2)*Math.PI/180*h_Len);
Point hourPoint = new Point(hour_X,hour_Y);

//以不同的顏色連接
myPen = new Pen(Color.Blue,1);
g.DrawLine(myPen,centerPoint,secPoint); //連接原點和秒針頂點
myPen = new Pen(Color.Green,2);
g.DrawLine(myPen,centerPoint,minPoint); //連接原點和分針頂點
myPen = new Pen(Color.Red,3);
g.DrawLine(myPen,centerPoint,hourPoint); //連接原點和時針頂點
g.Dispose(); //釋放Graphics對象使用的所有資源

 

要畫出一條直線,必須要得到這個直線的兩個頂點坐標(biāo),在這個程序里,三根表針有一個共同的原點(表盤中心點),然后如何得到另外一個點就是我們接下來要做的工作了

 

我們先來回顧一下三角函數(shù)的概念,sin值是 對邊/斜邊 得到,cos值是 鄰邊/斜邊得到,要求出這個點的坐標(biāo)就是求出這個三角形的兩條邊,一條邊的長度為X,另一條的長度為Y?,F(xiàn)在我們已經(jīng)知道的是斜邊的長度,要求出這兩條邊,就要先知道弧度值

我們先來考慮最長的秒針,它每一秒都會移動一個角度,這個角度我們可以計算出來:
360/60=6
得到6度,這不難理解,因為整個圓是360度,一般的時鐘在相鄰小時之間又有5個刻度,所以一共是12*5=60個刻度,然后用360/60=6得到秒針一秒走6度,在程序里必須要將角度轉(zhuǎn)化成弧度才能進(jìn)行sin運算,所以還要乘以 PI/180(PI為圓周率)

有了這個弧度值,我們就可以得到每一秒秒針的頂點坐標(biāo)了(以在第一區(qū)間考慮):
sec_X = centerPoint.X + sin(6*PI/180)*當(dāng)前秒鐘值*s_Len
sce_Y = centerPoint.Y - cos(6*PI/180)*當(dāng)前秒鐘值*s_Len

接下來處理時針,因為我們這只是個很簡單的模擬,所以就不需要對細(xì)節(jié)作過多的處理,就讓它每過一分鐘就跳到下一個刻度,這樣求時針的頂點坐標(biāo)和求秒針的就是一樣的算法
min_X = centerPoint.X + sin(6*PI/180)*當(dāng)前分鐘值*m_Len
min_Y = centerPoint.Y - cos(6*PI/180)*當(dāng)前分鐘值*m_Len

時針的處理方式要不同,因為時針的取值只有12個數(shù)字,而分鐘和秒針都有60個數(shù)字,如果以之前的方式處理時針,效果就是時針到點的那一瞬間它一下子轉(zhuǎn)30度,當(dāng)然不會有這樣效果的時鐘。那么我們該如何處理這個棘手的時針呢?

假如現(xiàn)在是06:45:30,在整6點時它的度數(shù)是30*6,整7點是30*7,為了不至于將改變?nèi)谧詈罂贪l(fā)生,我們加入時針值來參與計算,這樣當(dāng)前時間就是h*30+m/2,m為60時 m/2=30 ,也就是 m/2這個值在0--30之間,當(dāng)角度變化為30度時,就指到了下一個整點

這樣我們得到了時針的算法
hour_X = centerPoint.X + sin((h*30+m/2)*PI/180)*h_Len
hour_Y = centerPoint.Y - cos((h*30+m/2)*PI/180)*h_Len

最關(guān)鍵的代碼處理了,剩下的工作就簡單了,我們在程序里加入一個標(biāo)簽lblTime,來顯示當(dāng)前時間

string TimeInString = "";
int hour = DateTime.Now.Hour;
int min = DateTime.Now.Minute;
int sec = DateTime.Now.Second;
TimeInString = (hour<10)? "0"+hour.ToString():hour.ToString();
TimeInString += (min<10)? "0"+min.ToString():min.ToString();
TimeInString == (sec<10)? "0"+sec.ToString():sec.ToString();
lblTime.Text = TimeInString;

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多