ZedGraph源碼學習(一)


因工作原因,學習相關ZedGraph源碼來解決一些問題。剛看到這個開源圖表控件時,感覺還是短小精悍的。

結合ZedGraph控件的例子大致看了下對應的源碼,寫下點感悟。

這里先大致說一些ZedGraph里的元素。

1.Panel:ZedGraph控件是如何畫出來的,就是這這個上面畫出來,后面的元素如坐標軸,線條,餅圖。

2.Axis:軸線,任何二維線型、條型、餅型圖表都需要一個坐標軸,至少有X軸,Y軸,然后我們才能在上面畫相應的線條,餅型等元素。

3.CurveItem:我們剛說到在有坐標軸后,那么需要畫我們的線條,條型,餅型什么的,CurveItem就是存儲我們的數據然后畫出對應的圖形。

4.GraphObj:我們在整個Panel里可能要標出一些信息,如某點要添加相應描述,或是我們要標示有一部分是警告區域,都可以由這個來完成。

5.MajorTic與MinorTic:這二個對象都是針對Axis來說的,主要是描述上面的軸線上的主高刻度與副刻度。

6.Scale:這個和上面的對象一樣是Axis來說的,主要是描述軸線上的刻度顯示的對應的數字與標識。

7.PointPair:這個就是針對CurveItem來說的,CurveItem里保存着相應的數據,而這些數據就放在PointPair隊例里。

這些其實就是構成統計圖一些主要元素了,當然還有一些用於輔助的如:Legend(簡單來說就是對應CurvItem圖形的縮微圖),Fill(用於填充對象的),Border(描述元素邊界的),Symbol(點上的圖形).

上面的1-7中,除5,6外都是有對應的集合類。

它們之間的關系如下。

Panel可以包含Axis,CurveItem,GraphObj這些元素的集合,而在其中一個CurveItem可以對應一個X軸和Y軸,也可以多個CurveItem對應一個X軸,而GraphObj與Axis和CurveItem沒有直接關系。

CurveItem里包含着PointPair的集合,而Axis包含着Tic與Scale信息。

這里我先給出一些PaneBase相關的源碼。

在這個類里,有個屬性叫BaseDimension。

	public float BaseDimension
	{
		get { return _baseDimension; }
		set { _baseDimension = value; }
	} 

在源代碼里給出一段說明,如果BaseDimension=8英寸,在chart圖有8英寸寬的時候,如果標題為14像素那么高,那么在chart圖縮小到4英寸寬的時候,標題也會縮小到7個像素那么高。

是不是有點湖里湖塗的,在這里我先解釋一下英寸與像素的關系,這個還關系到另外一值,DPI(點每英寸),這個和顯示器有關,現在的顯示器一般是96DPI吧,老一點的一般是72DPI,在這里面也是用的72DPI,在這里8英寸用96DPI就是768像素。

這里先到這里,我們看下,它是如何用達到伸縮Chart圖而引起相應Title跟着伸縮的。先看如下一段代碼。

		public float CalcScaleFactor()
		{
			float scaleFactor; //, xInch, yInch;
			const float ASPECTLIMIT = 1.5F;
			
			// if font scaling is turned off, then always return a 1.0 scale factor
			if ( !_isFontsScaled )
				return 1.0f;

			if ( _rect.Height <= 0 )
				return 1.0F;
			float length = _rect.Width;
			float aspect = _rect.Width / _rect.Height;
			if ( aspect > ASPECTLIMIT )
				length = _rect.Height * ASPECTLIMIT;
			if ( aspect < 1.0F / ASPECTLIMIT )
				length = _rect.Width * ASPECTLIMIT;

			scaleFactor = length / ( _baseDimension * 72F );

			// Don't let the scaleFactor get ridiculous
			if ( scaleFactor < 0.1F )
				scaleFactor = 0.1F;
						
			return scaleFactor;
		} 

這段上有說明,得到一個比例因子,用於繪制元素,這段代碼很簡單,它首先會得到判斷有沒設置字體可以縮放,如不可以直接返回1,然后取panel自身的寬度,然后取寬與長的比例,如果寬大於1.5倍的長,那么取1.5倍的長,如果長大於寬1.5倍的長,則取寬的1.5倍長,如果不在這范圍,就取其寬度。而這個比例因子就是這個前面所說的BaseDimension所點的像素點(不過是老機器上的),也就是576,就是說長寬適合,寬為576的話,是不會發生任何縮放的。

得到這個比例因子后能做什么了?繪圖,能繪你伸縮chart圖成任何比例都還能顯示比例適合的圖,看如下一段代碼。

public RectangleF CalcClientRect( Graphics g, float scaleFactor )
		{

			float charHeight = _title._fontSpec.GetHeight( scaleFactor );

            RectangleF innerRect = new RectangleF(
                            _rect.Left + _margin.Left * scaleFactor,
                            _rect.Top + _margin.Top * scaleFactor,
                            _rect.Width - scaleFactor * (_margin.Left + _margin.Right),
                            _rect.Height - scaleFactor * (_margin.Top + _margin.Bottom));

			if ( _title._isVisible && _title._text != string.Empty )
			{
				SizeF titleSize = _title._fontSpec.BoundingBox( g, _title._text, scaleFactor );
				// Leave room for the title height, plus a line spacing of charHeight * _titleGap
				innerRect.Y += titleSize.Height + charHeight * _titleGap;
				innerRect.Height -= titleSize.Height + charHeight * _titleGap;
			}

			// Calculate the legend rect, and back it out of the current ChartRect
			//this.legend.CalcRect( g, this, scaleFactor, ref innerRect );

			return innerRect;
		}

這一段代碼是為了得到Chart圖除標題外的可用面積,這里我只看中間得到中間那段,我用如下圖來說明。

1111ssss

這里可以看到我們伸縮外面如何通過比例因子來影響里面元素大小了。

其實在PaneBase里的Draw()函數里就看到,首先是得到比例因子,然后再把比例因子當做各個繪制元素的參數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM