Qt學習之路: QPainter
Qt的繪圖系統允許使用相同的API在屏幕和打印設備上進行繪製。整個繪圖系統基於QPainter,QPainterDevice和QPaintEngine三個類。
QPainter用來執行繪製的操作;QPaintDevice是一個二維空間的抽象,這個二維空間可以由QPainter在上面進行繪製;QPaintEngine提供了畫筆painter在不同的設備上進行繪製的統一的接口。QPaintEngine類用在QPainter和QPaintDevice之間,並且通常對開發人員是透明的,除非你需要自定義一個設備,這時候你就必須重新定義QPaintEngine了。
下圖給出了這三個類之間的層次結構(出自Qt API 文檔):
這種實現的主要好處是,所有的繪製都遵循着同一種繪製流程,這樣,添加可以很方便的添加新的特性,也可以爲不支持的功能添加一個默認的實現方式。另外需要說明一點,Qt提供了一個獨立的QtOpenGL模塊,可以讓你在Qt的應用程序中使用OpenGL功能。該模塊提供了一個OpenGL的模塊,可以像其他的Qt組件一樣的使用。它的不同之處在於,它是使用OpenGL作爲顯示技術,使用OpenGL函數進行繪製。對於這個組件,我們以後會再介紹。
通過前面的介紹我們知道,Qt的繪圖系統實際上是說,使用QPainter在QPainterDevice上面進行繪製,它們之間使用QPaintEngine進行通訊。好了,下面我們來看看怎麼使用QPainter。
首先我們定義一個組件,同前面的定義類似:
class PaintedWidget
: public QWidget
{
public:
PaintedWidget();
protected:
void paintEvent(QPaintEvent *event);
};
這裏我們只定義了一個構造函數,並且重定義paintEvent()函數。從名字就可以看出,這實際上是一個事件的回調函數。請注意,一般而言,Qt的事件函數都是protected的,所以,如果你要重寫事件,就需要繼承這個類了。至於事件相關的東西,我們在前面的內容已經比較詳細的敘述了,這裏不再贅述。
構造函數裏面主要是一些大小之類的定義,這裏不再詳細說明:
PaintedWidget::PaintedWidget()
{
resize(800, 600);
setWindowTitle(tr("Paint Demo"));
}
我們關心的是paintEvent()函數的實現:
void PaintedWidget::paintEvent(QPaintEvent
*event)
{
QPainter painter(this);
painter.drawLine(80, 100, 650, 500);
painter.setPen(Qt::red);
painter.drawRect(10, 10, 100, 400);
painter.setPen(QPen(Qt::green, 5));
painter.setBrush(Qt::blue);
painter.drawEllipse(50, 150, 400, 200);
}
爲了把我們的程序運行起來,下面是main()函數:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
PaintedWidget w;
w.show();
return app.exec();
}
運行結果如下所示:
首先,我們聲明瞭一個QPainter對象。注意,我們在這個函數的棧空間建立了對象,因此不需要delete。
QPainter接收一個QPaintDevice*類型的參數。QPaintDevice有很多子類,比如QImage,以及QWidget。注意回憶一下,QPaintDevice可以理解成要在哪裏去畫,而現在我們希望在這個widget上畫,因此傳入的是this指針。
QPainter有很多以draw開頭的函數,用於各種圖形的繪製,比如這裏的drawLine,drawRect和和drawEllipse等。具體的參數請參閱API文檔。下圖給出了QPainter的draw函數的實例,本圖來自C++ GUI Programming with Qt4, 2nd Edition.