QT開發(十四)——QT繪圖系統
QT開發(十四)——QT繪圖系統
一、QT繪圖原理
Qt4中的2D繪圖系統稱為Arthur繪圖系統,可以使用相同的API在螢幕上和繪圖裝置上進行繪製,主要基於QPainter、QPainterDevice和 QPainterEngine。QPainter執行繪圖操作,QPainterDevice提供繪圖裝置,是一個二維空間的抽象,QPainterEngine提供一些介面。QPainter用來執行具體的繪圖相關操作,如畫點,畫線,填充,變換,alpha通道等。QPaintDevice類是能夠進行繪圖的物件的基類,QWidget,QPixmap,QPicture,QImage,以及QPrinte
QT中Arthur繪圖框架中的基本繪圖元素是畫筆,畫刷。 QPainter類具有GUI程式需要的絕大多數函式,能夠繪製基本圖形(點,線,矩形,多邊形等)以及複雜的圖形(如繪圖路徑)。使用繪圖路徑(QPaintPath)的優點是複雜形狀的圖形只用生成一次,再使用的時候只需要呼叫QPainter::drawPath()就可以繪製。QPainterPath物件可以用來填充,繪製輪廓。 線和輪廓都可以用畫筆(QPen)進行繪製,畫刷(QBrush)進行填充。畫筆定義風格(線形),寬度,筆尖畫刷以及端點是如何繪製的(cap-style),端點的連線方式(join-style)
通常情況下QPainter以預設的座標系統進行繪製,也可以用QMatrix類對座標進行變換。 當繪製時,可以使用QPainter::SetRenderHint函式設定繪圖引擎是否啟用反鋸齒功能使圖變得平滑。
QPainter::Antialiasin
1、重寫重繪事件處理函式實現繪圖
重繪事件處理函式:
void QWidget::paintEvent ( QPaintEvent * event )
基礎部件類Qwidget提供的paintEvent函式,是純虛擬函式;Qwidget的子類要使用paintEvent函式必須重新實現。在三種情況會發生重繪事件呼叫paintEvent函式:
A、當視窗部件第一次顯示時,系統會自動產生一個繪圖事件
B、repaint()與update()函式被呼叫時
C、當視窗部件被其他部件遮擋,然後又再次顯示出來時,就會對隱藏的區域產生一個重繪事件
D、重新調整視窗大小時
2、通過事件過濾器實現重繪
二、繪圖工具
繪圖時需要先定義一個QPainter類物件,繪圖工具可以使Qpen(畫筆)和QBrush(畫刷)。Qpen(畫筆)來繪製輪廓線,QBrush(畫刷)用來填充,使用QPen寫文字時還可以指定字型(QFont類)。
1、QPen畫筆
畫筆的屬性包括線型,線寬,顏色等。
A、QPen主要成員函式如下:
QPen(Qt::PenStyle style)
QPen(const QColor & color)
QPen(const QBrush & brush, qreal width, Qt::PenStyle style = Qt::SolidLine, Qt::PenCapStyle cap = Qt::SquareCap, Qt::PenJoinStyle join = Qt::BevelJoin)
QPen(const QPen & pen)
void setBrush(const QBrush & brush)
void setCapStyle (Qt::PenCapStyle style)
void setColor (const QColor & color)
void setJoinStyle (Qt::PenJoinStyle style)
void setWidth (int width)
畫筆的屬性可以在建構函式中指定,也可以使用setStyle(),setWidth(),setBrush(),setCapStyle(),setJoinStyle()等函式設定畫筆的各項屬性。Qt中使用Qt::PenStyle定義了6種畫筆風格,分別是Qt::SolidLine,Qt::DashLine,Qt::DotLine,Qt::DashDotLine,Qt::DashDotDotLine,Qt::CustomDashLine。自定義線風格(Qt::CustomDashLine),需要使用QPen的setDashPattern()函式來設定自定義風格。
畫筆的設定程式碼如下: QPainter painter(this);
QPen pen(Qt::green, 3, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin);
painter.setPen(pen);
等價於如下程式碼:
QPainter painter(this);
QPen pen; // creates a default pen
pen.setStyle(Qt::DashDotLine);
pen.setWidth(3);
pen.setBrush(Qt::green);
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
painter.setPen(pen);
B、畫筆風格
畫筆風格使用Qt::PenStyle列舉定義。
C、畫筆的端點風格( Qt::PenCapStyle) 畫筆端點風格決定了線的端點樣式,只對線寬大於1的線有效。Qt使用列舉定義了三種端點風格,分別為Qt::SqureCap,QT::FlatCap,Qt::RoundCap。
D、畫筆連線風格(Qt::PenJoinStyle) 畫筆連線風格是兩條線如何連線,連線風格對線寬大於等於1的線有效。Qt使用列舉定義了四種連線型別,分別是Qt::MiterJoin,Qt::BevelJoin,Qt::RoundJoin,Qt::SvgMiterJoin。
2、QBrush畫刷
在Qt中圖形使用QBrush進行填充,畫刷包括填充顏色和填充模式(風格)。
A、QBrush主要成員函式
QBrush(Qt::BrushStyle style)
QBrush(constQColor&color,Qt::BrushStyle style = Qt::SolidPattern)
QBrush(Qt::GlobalColor color,Qt::BrushStyle style= Qt::SolidPattern)
QBrush(const QColor & color, const QPixmap & pixmap)
QBrush(Qt::GlobalColor color, const QPixmap & pixmap)
QBrush(const QPixmap & pixmap)
QBrush(const QImage & image)
QBrush(const QBrush & other)
QBrush(const QGradient & gradient)
const QColor &color() const
const QGradient *gradient() const
const QMatrix &matrix() const
void setColor(const QColor & color)
void setColor(Qt::GlobalColor color)
void setMatrix(const QMatrix & matrix)
void setStyle(Qt::BrushStyle style)
void setTexture(const QPixmap & pixmap)
void setTextureImage(const QImage & image)
void setTransform(const QTransform & matrix)
Qt::BrushStyle style() const
QPixmap texture() const
QTransform transform() const
B、填充顏色
在Qt中,顏色使用QColor類表示,QColor支援RGB,HSV,CMYK顏色模型。QColor還支援alpha混合的輪廓和填充。RGB是面向硬體的模型,顏色由紅綠藍三種基色混合而成;HSV模型比較符合人對顏色的感覺,由色調(0-359),飽和度(0-255),亮度(0-255)組成;CMYK由青,洋紅,黃,黑四種基色組成,主要用於印表機等硬體拷貝裝置上,每個顏色分量的取值是0-255。
C、填充模式
填充模式通過列舉型別Qt::BrushStyle來實現,預設值是Qt::NoBrush,不進行任何填充;填充模式包括基本填充模式,漸變填充,和紋理填充模式。不同的填充模式顯示效果如下:
Qt4中,QBrush提供了三種漸變填充:線性(QLinearGradient),圓形(QRadialGradient)和圓錐漸變(QConicalGradient),所有的類都從QGradient類繼承。
線性漸變填充 線性漸變填充指定兩個控制點,畫刷在兩個控制點之間進行顏色插值。通過建立QLinearGradient物件來設定畫刷。 QLinearGradient linearGradient(0,0,200,100); linearGradient.setColorAt(0,Qt::red); linearGradient.setColorAt(0.5,Qt::green); linearGradient.setColorAt(1,Qt::blue); painter.setBrush(linearGradient); painter.drawRect(0,0,200,100); 在QGradient建構函式中指定線行填充的兩點分別為(0,0),(100,100)。 setColorAt()函式在0-1之間設定指定位置的顏色。圓形漸變填充 圓形漸變填充需要指定圓心,半徑和焦點。畫刷在焦點和圓上的所有點之間進行顏色插值,通過建立QRadialGradient物件設定畫刷。 QRadialGradient radialGradient(50,50,50,30,30); radialGradient.setColorAt(0.2,Qt::cyan); radialGradient.setColorAt(0.8,Qt::yellow); radialGradient.setColorAt(1,Qt::magenta); painter.setBrush(radialGradient); painter.drawEllipse(0,0,100,100);圓錐漸變填充 圓錐漸變填充指定圓心和開始角,畫刷沿圓心逆時針對顏色進行插值,通過建立QConicalGradient物件並設定畫刷。 QConicalGradient conicalGradient(60,40,30); conicalGradient.setColorAt(0,Qt::gray); conicalGradient.setColorAt(0.4,Qt::darkGreen); conicalGradient.setColorAt(0.6,Qt::darkMagenta); conicalGradient.setColorAt(1,Qt::drakBlue); painter.setBrush(conicalGradient); painter.drawEllipse(0,0,100,100);
其他填充模式
其他填充模式通過setStyle(Qt::BrushStyle style)函式進行設定。
如果實現自定義填充,可以使用QPixmap或者QImage物件進行紋理填充。兩種影象分別使用setTexture()和setTextureImage()函式載入紋理。
D、alpha通道 在windows,Mac OSX和有XRender擴充套件的X11系統上,Qt4能夠支援Alpha通道,通過使用Alpha通道,可以實現半透明效果,QColor類中定義了Alpha通道的透明度,0表示完全透明,255表示完全不透明。QWidget類有一個屬性windowOpacity,通過setWindowOpacity(qreal level)可以設定視窗的透明度。但該屬性和Alpha通道的原理並不相同,Qt4在Windows和Mac OS X平臺上才支援該屬性,但在X11平臺上卻需要Composite擴展才能工作。(alpha通道使用的是X11的xRender擴充套件)。
3、雙緩衝繪圖
在Qt4中,所有的視窗部件預設都使用雙緩衝進行繪圖。使用雙緩衝,可以減輕繪製的閃爍感。在有些情況下,使用者要關閉雙緩衝,自己管理繪圖。下面的語句設定了視窗部件的Qt::WA_PaintOnScreen屬性 ,就關閉了視窗部件的雙緩衝。 widget->setAttribute(Qt::WA_PaintOnScreen); Qt4不再提供異或筆,組合模式QPainter::CompostionMode_Xor()並不是異或筆,Qt4只提供了QRubberBand實現矩形和直線的繪圖反饋。要實現在繪圖中動態反饋必須使用其他方法。程式中使用雙緩衝來解決這個問題。在繪圖過程中,一個緩衝區繪製臨時記憶體,一個緩衝區儲存繪製好的內容,最後進行合併。 在互動繪圖過程中,程式將影象緩衝區複製到臨時緩衝區,並在臨時緩衝區上繪製,繪製完畢在將結果複製到影象緩衝區,如果沒有互動複製,則直接將影象緩衝區繪製顯示到螢幕上。
4、繪圖路徑
繪圖路徑(painter path)由基本圖元(矩形,橢圓,直線,曲線)組成,繪圖路徑可以是閉合的路徑,如矩形和圓,或者是非閉合的路徑,如直線和曲線。繪圖路徑在Qt中使用QPainterPth類表示,提供了繪圖操作的容器,可以使圖形能夠複用。繪圖路徑可以進行填充,顯示輪廓和裁剪。要生成可填充的輪廓的繪圖路徑,可以使用QPainterPathStroker類。使用QPainterPath的優點是複雜的圖形只需建立一次,就可以多次使用。QPainterPath物件可以是只有起點的空路徑,或者從其他QPainterPath物件複製,建立了QPainterPath物件後,可以使用lineTo(),cubicTo(),quadTo() 函式將直線和曲線新增到路徑中來,直線和曲線從currentPosition()開始繪製。currentPosition()總是返回最後的子路經繪製的終點。使用moveTo()函式可以在不增加路徑的情況下移動currentPositon(),它關閉了一個子路經,開始一個新的子路經。 closeSubPath()也可以關閉當前路徑,並從currentPosition()連線一條直線到繪圖路徑的起點。QPainter可以使用 addEllipse(),addPath(),addRect(),addRegion(),
addText()將Qt的一些基本圖元加入繪圖路徑。一個已有的繪圖路徑可以通過connectPath()函式加入到另一個繪圖路徑中。箭頭的繪製程式碼如下:QPainterPath path;
path.moveTo(10,100);
path.cubicTo(10,100,100,10,200,70);
path.lineTo(200,50);
path.lineTo(220,80);
path.lineTo(200,110);
path.lineTo(200,90);
path.cubicTo(200,100,100,50,50,100);
QPainter painter(this);
QPen pen(QColor(255,0,0),2);
painter.setPen(pen);
painter.drawPath(path);
Qt提供了兩種填充方式,Qt::OddEventFill和Qt::WindingFill。Qt::OddEvent是預設的填充規則,指定QPainterPath使用奇偶填充規則,奇偶填充規則判斷一個點是否在路徑圖形內的方法是從該點畫一條水平線到路徑外,計算水平線和路徑的交點數,如果交點是奇數個則說明該點在路徑圖形內。QPainterPath還有一些函式可以獲取路徑資訊,如elementAt()函式可以取出指定的子路經元素,isEmpty()函式判斷當前路徑是否為空。controlPointRect()函式返回路徑中所有的點和控制點的矩形,controlPointRect函式執行速度比返回精確包容框boundingRect()函式快得多。contains()函式判斷一個點或一個矩形是否在路徑內。intersects()判斷指定的矩形與路徑是否相交。QPainterPath可以將矩形圖形轉換為其他圖形,如使用toFillPolygon(),toFillPolygon(),toSubpathPOlygons()函式將路徑轉化為多邊形。QPainterPath還可以使用文字作為路徑。
使用線性漸變填充的文字路徑實現程式碼:QPainter painter(this);
QLinearGradient linearGrad(QPointF(200,0),QPointF(1000,0));
linearGrad.setColorAt(0,Qt::black);
linearGrad.setColorAt(1,Qt::white);
QFont font("隸書",80);
font.setBold(true);
QPainterPath textPath;
textPath.addText(200,300,font,tr("電子工業出版社"));
painter.setBrush(linearGrad);
painter.drawPath(textPath);
三、繪圖裝置
QPaintDevice類是繪製裝置的基類,QPainter能夠在QPaintDevice子類QWidget,QImage,QPixmap,QGLWidget,QGLPixelBuffer,QPicture,QPrinter,QSvgGenerator上進行繪製。要實現自定義的繪圖裝置,必須從QPaintDevice類繼承並實現其虛擬函式QPaintDevice::paintEngine(),paintEngine()將通知QPainter能夠在自定義的裝置上繪製圖形,同時還需要從QPaintEngine類繼承自定義的圖形繪製引擎。
1、QWidget
QWidget是所有使用者介面元素的基類,視窗部件是使用者介面的原子元素,接受滑鼠、鍵盤、視窗系統的其他事件並在螢幕上繪製自己。
2、QImage
QImage類提供了與硬體無關的影象表示,為直接操作畫素提供優化,QImage支援單色、8-bit、32-bit和alpha混合影象,使用QImage的優點在於可以獲得平臺無關的繪製操作,同時影象可以不必在GUI執行緒中處理。
3、QPixmap
QPixmap是後臺顯示的影象,為在螢幕上顯示影象提供優化,不同於QImage,QPixmap的影象資料使用者不可見,由底層視窗系統管理,為了優化QPixmap影象,Qt提供了QPixmapCache類來儲存臨時的pixmap。Qt還提供了QPixmap的繼承類QBitmap類,QBitmap表示單色的pixmap,主要用來建立自定義的QCursor和QBrush物件,構造QRegion物件,設定pixmap和視窗部件的掩碼。
4、OPenGLWidget
Qt提供了QtOpenGL模組來實現OpenGL操作,QGLWidget允許使用OpenGL API進行繪製。QGLWidget是QWidget的子類,QPainter可以在上面繪製,因此Qt能夠利用OpenGL完成繪製操作,如變換和繪製pixmap。
5、QGLPixelBuffer
QGLPixelBuffer從QPaintDevice繼承,封裝了OpenGLpbuffer,使用pbuffer繪製通常是全硬體加速,比使用QPixmap繪製更加迅速。
6、QGLFrameBufferObject
QGLFrameBufferObject從QPaintDevice繼承,QGLFrameBufferObject封裝了OpenGL frameBuffer物件,FrameBuffer用來實現後臺螢幕繪製,比pixel buffer更好。
7、QPicture
QPicture類是能夠記錄和重演QPainter命令的繪圖裝置,picture序列化painter的命令為平臺無關的格式,QPicture同時也與解析度無關,如QPicuture能夠在不同的裝置上(svg,pdf,ps印表機和螢幕)有一樣的顯示。QPicture::load()和QPicture::save()函式分別完成載入和儲存影象。
8、QPrinter
QPrinter類是在印表機上繪製的繪圖裝置,在Windows和MAC OS X上,QPrinter使用內建的印表機驅動程式,在X11上,QPrinter上傳postscript程式碼併發送給lpr,lp或者其他列印程式,QPrinter可以在任意其他QPrintEngine物件上列印,也可以直接生成PDF檔案。 QPrintEngine類定義了QPrinter如何和其他印表機系統互動的介面,主要建立自己的列印引擎時,可以從QPaintEngine和QPaintEngine上繼承。
四、QPainter類成員函式
主要的繪圖成員函式如下:
drawArc() 弧 drawChord() 弦 drawConvexPolygon() 凸多邊形 drawEllipse() 橢圓 drawImage() QImage表示的影象 drawLine() 線 drawLines() 多條線 drawPath() 路徑 drawPicture() 按QPainter指令繪製 drawPie() 扇形 drawPixmap() QPixmap表示的影象 drawPoint() 點 drawPoints() 多個點 drawPolygon() 多邊形 drawPolyline() 多折線 drawRect() 矩形 drawRects() 多個矩形 drawRoundRect() 圓角矩形 drawText() 文字 drawTiledPixmap() 平鋪影象 drawLineSegments() 繪製折線
設定好畫筆、畫刷就可以使用繪圖函式進行繪圖。
本文出自 “生命不息,奮鬥不止” 部落格,謝絕轉載!