我覺得繪制只需要考慮幾個問題。簡單地說就是誰在什么地方畫什么? 在Qt中可以這么回答:QPainter在QPainterDevice中畫想畫的東西。
舉個例子:用QtCreator向導新建一個項目,基類選擇QWidget。我們重載paintEvent這個函數。
void Widget::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.drawRect(50,50,100,100); }
QPainter在this(this指的這個QWidget,QWidget繼承於QPainterDevice)上畫了一個矩形。可以看到結果如下:

http://www.fearlazy.com/index.php/post/6.html
我們說Qt的繪制工作是由QPainter來完成的,但是它也不能空着手干活。通常情況下,它需要用到兩樣工具:一個是QPen(畫筆),另一個則是QBrush(畫刷)。
畫筆是用來繪制輪廓的,畫刷則是用來填充的。以矩形為例畫筆控制的是矩形邊框的繪制,畫刷控制邊框包圍區域的繪制。我們接着上一篇的例子:
void Widget::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.setPen(QPen(Qt::red)); //設置畫筆為紅色 painter.setBrush(QBrush(Qt::green)); //設置畫刷為綠色 painter.drawRect(50,50,100,100); }
在例子中增加兩行代碼,設置了QPainter的畫筆和畫刷。效果如下:

那么問題來了,為什么什么上一篇的例子中我們沒有設置畫筆和畫刷也可以繪制呢?
http://www.fearlazy.com/index.php/post/7.html
上一節留下一個問題,答案其實很簡單。是默認值在工作。QPainter默認了一個畫筆和畫刷。說到這,我們就聊聊畫筆這東西。上一節的例子中我們設置了畫筆的顏色。當然畫筆不止有這點本事。它擁有style、width、brush、capStyle和joinStyle這幾個屬性。
1.style定義了繪制的線的類型。指的是實線、虛線或是點線。Qt中有個枚舉Qt::PenStyle定義了畫筆的style。

歸納來說就是實線、虛線和點,其中Qt::CustomDashLine不是一種畫筆類型而是一類,可以自定義實線長度、虛線長度。
2.width定義了畫筆的寬度。
3.brush定義了畫筆的填充顏色。
4.capStyle定義了線的末端的繪制樣式。Qt中枚舉Qt::PenCapStyle有如下三個值。

SquareCap 和 Flatcap的區別在於FlagCap的末端及點的位置,而SquareCap有再向外延伸了半個寬度。
5.joinStyle定義了兩條線連接處的繪制定義。有枚舉Qt::PenJoinStyle,具體值如下:

例:

http://www.fearlazy.com/index.php/post/8.html
說完畫筆,接下來說說畫刷。畫刷(QBrush)包含了樣式、顏色、漸變和材質(英文texture,材質是我翻譯的)。 但是顏色、漸變和材質不會同時出現。這取決於樣式。
Qt定義了很多畫刷的樣式:

其中Qt::LinearGradientPattern、Qt::RadialGradientPattern和Qt::ConicalGradientPattern是漸變類型的樣式。Qt::TexturePattern是材質類型的畫刷樣式。
要使用漸變的樣式需要在構造畫刷時傳入一個漸變對象,可以是QConicalGradient、QLinearGradient或QRadialGradient。
要使用材質類型的樣式時可以在構造一個畫刷時傳入一個QPixmap或QImage對象。也可以在構造畫刷對象后調用setTexture或setTextureImage。
例:

http://www.fearlazy.com/index.php/post/9.html
到目前為止我們已經畫了好幾個矩形了,但是如果你認為QPainter只會畫矩形,那就太小看它了。QPainter會畫的東西可多了。點、線、圓、弧形、圖片、路徑等等。
接下來畫畫簡單的東西:
1.畫點:
void drawPoint(const QPointF& position);
void drawPoint(const QPoint& position);
void drawPoint(int x, int y);
輸入點的坐標即可。
2.畫直線:
void drawLine(const QLineF& line);
void drawLine(const QLine& line);
void drawLine(int x1, int y1, int x2,int y2);
輸入一個線對象,或者線的兩個點。
3.畫橢圓:
void drawEllipse(const QRectF& rectangle);
void drawEllipse(const QRect& rectangle);
void drawEllipse(int x, int y, int width, int height);
void drawEllipse(const QPointF& center, qreal rx, qreal ry);
void drawEllipse(const QPoint& center,int rx, int ry);
畫橢圓有兩種方式:
第一種是輸入橢圓的外切矩形,可調用前三個接口。
第二種是輸入圓心以及x半徑和y半徑,調用后兩個接口。
4.畫圖片:
畫圖片的接口太多,只列舉兩個:
void drawPixmap(const QRectF& target, const QPixmap& pixmap, const QRectF& source);
void drawPixmap(const QPointF& point, const QPixmap& pixmap);
這兩個接口的區別是第一種指定了繪制目標的一個區域,圖片會縮放后畫到該區域。第二種指定了繪制目標的一個位置。
第一個接口中的source指的是繪制圖片的區域,通過這個參數可以設置你要繪制圖片中的哪一部分。
http://www.fearlazy.com/index.php/post/10.html
QPainter是個多才多藝的家伙,除了會畫畫還會寫字。而且寫字的姿勢還挺多。

這么多函數,看得人眼花繚亂。不過仔細觀察一下會發現很多參數都是重復的。
text: 就是要寫的文字。
position: 指定寫的文字的位置。(x,y)同理。
rectangle:指定寫的文字的矩形區域,這個和繪制圖片的矩形不一樣,它不會根據矩形縮放文字。(x,y,width,height)同理。
flag:指定繪制的標志,如左對齊、右對齊、居中等等。
boundingRect:指的是繪制的文字實際占用的矩形區域。是個返回值。
option: 描述了文字,例如對齊方式、文字方向等。
例:

例子指定在矩形(50,80,60,30)中以居中的位置繪制“這是文本”幾個字。接着又繪制了這個矩形以及函數返回給我們的實際占用區域。可以看出文字沒有占滿指定矩形范圍。實際上文字的大小取決於字體QFont。
我們設置字體看看效果:

文字字體設置太大已經超出了指定的繪制范圍了。超出的部分則不會被繪制。
QPainter繪制文字除了指定繪制區域外,還可以指定位置進行繪制。這種方式不需要設置多余的參數,缺點就是使用時不太好控制。
例:

例子中除了繪制文本外,我們還這個位置用紅點描出來了,可以看出所謂的位置指的是文本左下角的位置。
http://www.fearlazy.com/index.php/post/15.html
在這之前,我們用QPainter繪制了不少東西,這些東西都是規規矩矩很正經的玩意。其實QPainter也有着它不正經的一面。有時它不按套路出牌不在指定的位置畫,有時畫的大一點或小一點又或者畫的東倒西歪的。但只要你掌握了它的變化的套路並加以利用,反而能為繪制創造出更多新意。接下來讓我們認識一下他們。
偏移(translate)
默認情況下,繪制的原點在設備的左上角。通過設置偏移原點發生變化,繪制的內容也會相對應變化。
例:
偏移前用黑色在(50,110)處繪制了幾個字,並且繪制了原點到文本位置的直線。 在偏移(50,50)后用綠色繪制了同樣的內容。可以看出偏移后相對於原來的位置整體偏移了(50,50)。我們可以這么去理解:translate改變了繪制的原點,而我們繪制時使用的坐標都是相對於原點而言的。
旋轉(rotate)
旋轉,顧名思義就是讓繪制的東西旋轉。它是相對於原點按順時針進行旋轉的。
例:

例子中我們先偏移了(100,100),因為旋轉是相對於原點位置旋轉的,如果不往右偏移點旋轉后估計這就看不到了。
縮放(scale)
scale可以對繪制的內容放大或縮小,它包含x軸和y軸兩個方向。當輸入的值大於1時放大,當輸入的值小於1時則縮小。
例:

從圖中可以看出不僅文字的大小變小了,連距離也被縮小了。縮放的計算也是相對於原點而言的。
http://www.fearlazy.com/index.php/post/18.html
