Qt 之圖形(QPainter 的基本繪圖)
簡述
Qt 中提供了強大的 2D 繪圖系統,可以使用相同的 API 在螢幕和繪圖裝置上進行繪製,它主要基於QPainter、QPaintDevice 和 QPaintEngine 這三個類。
- QPainter 用於執行繪圖操作,其提供的 API 在 GUI 或 QImage、QOpenGLPaintDevice、QWidget 和QPaintDevice 顯示圖形(線、形狀、漸變等)、文字和影象。
- QPaintDevice 不直接繪製物理顯示畫面,而利用邏輯介面的中間媒介。例如,繪製矩形圖形時,為了將物件繪製到 QWidget、QGLPixelBuffer、QImage、QPixmap、QPicture 等多種介面中間,必須使用 QPaintDevice。
- QPaintEngine 提供了一些介面,可用於 QPainter 在不同的裝置上進行繪製。
繪圖系統由 QPainter 完成具體的繪製操作,QPainter 類提供了大量高度優化的函式來完成 GUI 程式設計所需要的大部分繪製工作。它可以繪製一切想要的圖形,從最簡單的一條直線到其他任何複雜的圖形,例如:點、線、矩形、弧形、餅狀圖、多邊形、貝塞爾弧線等。此外,QPainter 也支援一些高階特性,例如反走樣(針對文字和圖形邊緣)、畫素混合、漸變填充和向量路徑等,QPainter 也支援線性變換,例如平移、旋轉、縮放。
QPainter 可以在繼承自 QPaintDevice 類的任何物件上進行繪製操作。QPainter 也可以與 QPrinter 一起使用來列印檔案和建立 PDF 文件。這意味著通常可以用相同的程式碼在螢幕上顯示資料,也可以生成列印形式的報告。
QPainter 一般在部件的繪圖事件 paintEvent() 中進行繪製,首先建立 QPainter 物件,然後進行圖形的繪製,最後記得銷燬 QPainter 物件。當視窗程式需要升級或者重新繪製時,呼叫此成員函式。使用 repaint()和 update() 後,呼叫函式 paintEvent()。
|
繪製文字
void MainWindow::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
// 設定畫筆顏色
painter.setPen (QColor(0, 160, 230));
// 設定字型:微軟雅黑、點大小50、斜體
QFont font;
font.setFamily("Microsoft YaHei");
font.setPointSize(50);
font.setItalic(true);
painter.setFont(font);
// 繪製文字
painter.drawText(rect(), Qt::AlignCenter, "Qt");
}
首先為該部件建立了一個 QPainter 物件,用於後面的繪製。使用 setPen() 來設定畫筆的顏色(淡藍色)。通過使用 QFont 來構建我們想要的字型,setFamily()設定字型為微軟雅黑、setPointSize() 設定點大小30、setItalic() 設定斜體, 然後通過 setFont() 來設定字型,最後呼叫 drawText() 來實現文字的繪製,這裡的 rect() 是指當前窗體的顯示區域,Qt::AlignCenter 指文字居中繪製。
繪製直線
void MainWindow::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
// 反走樣
painter.setRenderHint(QPainter::Antialiasing, true);
// 設定畫筆顏色
painter.setPen(QColor(0, 160, 230));
// 繪製直線
painter.drawLine(QPointF(0, height()), QPointF(width() / 2, height() / 2));
}
首先我們通過 setRenderHint() 來設定反走樣,要麼繪製出來的線條會出現鋸齒,呼叫 setPen() 來設定畫筆顏色(淡藍色)。最後呼叫 drawLine() 來實現直線的繪製,其中 QPointF(0, height()) 是指直線的起點座標、QPointF(width() / 2, height() / 2) 是指直線的終點座標。
繪製矩形
void MainWindow::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
// 反走樣
painter.setRenderHint(QPainter::Antialiasing, true);
// 設定畫筆顏色、寬度
painter.setPen(QPen(QColor(0, 160, 230), 2));
// 設定畫刷顏色
painter.setBrush(QColor(255, 160, 90));
painter.drawRect(50, 50, 160, 100);
}
首先我們使用 setPen() 來設定畫筆顏色(淡藍色)、寬度(2 畫素),用來設定矩形區域的邊框。然後使用setBrush() 來設定畫刷顏色(橙色),用來填充矩形區域,最後呼叫 drawRect() 來實現矩形的繪製,其中引數依次順序為 x、y、w、h,是指區域從 x 為 50,y 為 50 的座標點起,寬度為 160,高度為 100 的矩形。
繪製弧線
void MainWindow::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
// 矩形
QRectF rect(90.0, 90.0, 80.0, 90.0);
// 起始角度
int startAngle = 30 * 16;
// 跨越度數
int spanAngle = 120 * 16;
QPainter painter(this);
// 反走樣
painter.setRenderHint(QPainter::Antialiasing, true);
// 設定畫筆顏色、寬度
painter.setPen(QPen(QColor(0, 160, 230), 2));
// 繪製弧線
painter.drawArc(rect, startAngle, spanAngle);
}
畫弧線時,角度被分成了十六分之一,就是說,如果要 30 度,就需是 30*16。它有起始角度和跨度,還有位置矩形,所以,要想畫出自己想要的弧線,就需要大概估算出各個引數的預估值。
繪製橢圓
void MainWindow::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
// 反走樣
painter.setRenderHint(QPainter::Antialiasing, true);
// 設定畫筆顏色、寬度
painter.setPen(QPen(QColor(0, 160, 230), 2));
// 繪製橢圓
painter.drawEllipse(QPointF(120, 60), 50, 20);
// 設定畫刷顏色
painter.setBrush(QColor(255, 160, 90));
// 繪製圓
painter.drawEllipse(QPointF(120, 140), 40, 40);
}
這裡我們繪製了一個橢圓和一個圓形,都是呼叫 drawEllipse() 介面,我們可以很輕易的發現,如果為橢圓的時候,後面兩個引數不一樣,圓形則相同。首先我們來看第一個引數 QPointF 是指橢圓的中心點相對當前窗體 QPoint(0, 0) 點的位置,後面的引數指橢圓的 x 軸及 y 軸的半徑。
繪製多邊形
void MainWindow::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
// 反走樣
painter.setRenderHint(QPainter::Antialiasing, true);
// 設定畫筆顏色
painter.setPen(QColor(0, 160, 230));
// 各個點的座標
static const QPointF points[4] = {QPointF(30, 40), QPointF(60, 150), QPointF(150, 160), QPointF(220, 100)};
// 繪製多邊形
painter.drawPolygon(points, 4);
}
首先,我們定義一個個座標點的位置,這裡有四個點,分別為:QPointF(30, 40)、QPointF(60, 150)、QPointF(150, 160)、 QPointF(220, 100),然後呼叫 drawPolygon() 將各個點連線起來,繪製為多邊形。
繪製圖片
void MainWindow::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
// 反走樣
painter.setRenderHint(QPainter::Antialiasing, true);
// 繪製圖標
painter.drawPixmap(rect(), QPixmap(":/Images/logo"));
}
通過 drawPixmap() 來繪製圖片,我們可以指定圖片繪製的區域 QRect,這裡為整個介面的區域,當介面伸縮的時候,圖片也會跟著伸縮。