一、概述
Qt的paint系統(tǒng)可以使用相同的API在屏幕和打印設(shè)備上進行繪圖,它主要是基于QPainter、QPaintDevice和QPaintEnengine類。
QPainter用于執(zhí)行繪制操作,QPaintDevice是一個二維空間的抽象,可以使用QPainter在其上進行繪制,QPaintEngine提供了 QPainter 用于在不同類型設(shè)備上繪制的界面。QPaintEngine 類由 QPainter 和 QPaintDevice 在內(nèi)部被使用,并且對我們應(yīng)用開發(fā)程序員隱藏,除非我們創(chuàng)建自己的繪圖設(shè)備類型。
這種方法的主要好處是,所有繪制都遵循相同的繪制通道,這使得添加新功能的支持變得容易,并為不支持的功能提供默認(rèn)實現(xiàn)。換句話說就是擴展性很強的。
二、繪圖設(shè)備和后端
QPaintDevice 類是可繪制對象的基類,即 QPainter 可以在任何 QPaintDevice 的子類上繪制。QPaintDevice 的繪圖功能由 QWidget、QImage、QPixmap、QPicture、QPrinter 和 QOpenGLPaintDevice 實現(xiàn)。
下面提到的這些類都是繼承了 QPaintDevice 因此就具備了 繪制的功能
1. Widget
QWidget類是Qt Widgets模塊中用戶界面元素的基類。它從window系統(tǒng)接收鼠標(biāo)、鍵盤和其他事件,并在屏幕上顯示自己。就是窗體系統(tǒng)中的重要一環(huán)
2. Image
QImage類提供了一個獨立于硬件的圖像表示,為I/O和直接像素訪問和操作進行了設(shè)計和優(yōu)化。QImage支持多種圖像格式,包括單色、8位、32位和alpha混合圖像。
使用QImage作為繪制設(shè)備的兩個優(yōu)點:
- 可以以一種平臺無關(guān)的方式保證任何繪制操作的像素準(zhǔn)確性。
- 繪圖可以在當(dāng)前GUI線程之外的另一個線程中執(zhí)行。
3. Pixmap
QPixmap類是為在屏幕上顯示圖像而設(shè)計和優(yōu)化的屏幕外圖像表示。與 QImage 不同,pixmap中的像素數(shù)據(jù)是內(nèi)部的,由底層窗口系統(tǒng)管理,即像素只能通過 QPainter 函數(shù)或?qū)?QPixmap 轉(zhuǎn)換為 QImage 來訪問。
為了優(yōu)化使用QPixmap繪圖,Qt提供了QPixmapCache類,該類可用于存儲臨時的pixmap,這些臨時的pixmap生成成本很高,而不會使用超過緩存限制的存儲空間。
Qt還提供了QBitmap便利類,它繼承了QPixmap。QBitmap保證單色(1位深度)像素圖,主要用于創(chuàng)建自定義QCursor和QBrush對象,構(gòu)造QRegion對象。
4. OpenGL繪制設(shè)備
如前所述,Qt提供了一些類,使得在Qt應(yīng)用程序中使用OpenGL變得容易。例如,QOpenGLPaintDevice啟用了用于QPainter渲染的OpenGL API。
5. Picture
QPicture類是一個記錄和回放QPainter命令的繪制設(shè)備。圖片以獨立于平臺的格式將 painter 命令序列化到IO設(shè)備。QPicture也是分辨率獨立的,即一個 QPicture 可以在不同的設(shè)備(例如svg, pdf, ps,打印機和屏幕)上顯示,看起來相同。
Qt提供了 QPicture::load() 和 QPicture::save() 函數(shù)以及用于加載和保存圖片的流操作符。
6. 自定義繪制后端
對新的后端的支持可以通過從QPaintDevice類派生并重新實現(xiàn)虛擬的 QPaintDevice::paintEngine() 函數(shù)來告訴 QPainter 應(yīng)該使用哪個繪制引擎在這個特定的設(shè)備上繪制。
要真正能夠在設(shè)備上繪制,這個繪制引擎必須是通過派生QPaintDevice 類創(chuàng)建的自定義繪制引擎。
三、繪圖與填充
1. Drawing
QPainter提供了高度優(yōu)化的函數(shù)來完成大多數(shù)GUI程序所需的繪圖。它可以繪制任何東西,從簡單的圖形基元(由QPoint、QLine、QRect、QRegion和QPolygon類表示)到復(fù)雜的形狀,如矢量路徑。在Qt矢量路徑由QPainterPath類表示。QPainterPath為繪制操作提供了一個容器,使圖形形狀能夠被構(gòu)建和重用。
1. QPainterPath
QPainterPath 是由直線和曲線組成的對象。例如,矩形由直線組成,橢圓由曲線組成。
與普通的繪制操作相比,painter paths的主要優(yōu)點是復(fù)雜的形狀只需要創(chuàng)建一次;然后只需調(diào)用QPainter::drawPath()函數(shù)就可以多次繪制它們。
QPainterPath對象可用于填充、輪廓和裁剪。要為給定的painter路徑生成可填充的輪廓,使用QPainterPathStroker類。
線和輪廓使用QPen類繪制。一支筆是由它的樣式(即它的線條類型)、寬度、筆刷、端點的繪制方式(cap-style)以及兩條連接的線之間的連接方式(join-style)來定義的。鋼筆的筆刷是一個QBrush對象,用于填充鋼筆生成的筆觸,即QBrush類定義了填充模式。
QPainter還可以繪制對齊的文本和像素地圖。
繪制文本時,字體使用 QFont 類指定。Qt 將使用指定屬性的字體,如果不存在匹配的字體,Qt將使用安裝的最接近的字體。實際使用的字體屬性可以使用 QFontInfo 類取得。此外,QFontMetrics 類提供字體測量,QFontDatabase 類提供有關(guān)底層窗口系統(tǒng)中可用字體的信息。
通常,QPainter在一個“自然”坐標(biāo)系中繪制,但它能夠使用 QTransform 類執(zhí)行 視圖 和 世界 坐標(biāo)系之間的轉(zhuǎn)換。有關(guān)更多信息,請參見坐標(biāo)系統(tǒng),它也描述了渲染過程,即邏輯表示和渲染像素之間的關(guān)系,以及反鋸齒繪制的好處。
2. 反鋸齒的繪圖
繪制時,像素渲染由 QPainter::Antialiasing 渲染提示控制。枚舉 QPainter::RenderHint 用于指定 QPainter 的標(biāo)志,這些標(biāo)志可能被任何給定的引擎使用,也可能不被任何給定的引擎使用。
QPainter::Antialiasing 值表示如果可能的話,引擎應(yīng)該消除圖元的邊緣,即通過使用不同的顏色強度平滑邊緣。
2. 填充 Filling
使用QBrush類填充形狀。畫筆是由它的顏色和樣式(即它的填充模式)定義的。
Qt中的任何顏色都由QColor類表示,該類支持RGB、HSV和CMYK顏色模型。QColor還支持alpha混合輪廓和填充(指定透明效果),并且該類與平臺和設(shè)備無關(guān)(使用QColormap類將顏色映射到硬件)。
可用的填充圖案由Qt::BrushStyle枚舉描述。這些包括基本模式,從統(tǒng)一的顏色到非常稀疏的模式,各種線條組合,梯度填充和紋理。Qt提供了QGradient類來定義自定義的漸變填充,而使用QPixmap類來指定紋理模式。
1. QGradient
QGradient類與QBrush類結(jié)合使用來指定梯度填充。
Qt 目前支持三種類型的漸變填充:線性漸變在起點和終點之間插入顏色,徑向漸變在焦點和圓周上的終點之間插入顏色,圓錐漸變在中心點周圍插入顏色。
四、坐標(biāo)系統(tǒng)
坐標(biāo)系統(tǒng)由QPainter類控制。與QPaintDevice和QPaintEngine類一起,QPainter構(gòu)成了Qt繪畫系統(tǒng)的基礎(chǔ)。QPainter用于執(zhí)行繪制操作,QPaintDevice是一個二維空間的抽象,可以使用QPainter在其上進行繪制,QPaintEngine提供了 QPainter 用于在不同類型設(shè)備上繪制的界面。
QPaintDevice 類是可繪制對象的基類:它的繪制功能由QWidget、QImage、QPixmap、QPicture和QOpenGLPaintDevice類繼承。繪制設(shè)備的默認(rèn)坐標(biāo)系統(tǒng)起源于左上角。x值向右增大,y值向下增大。在基于像素的設(shè)備上,默認(rèn)單位是一個像素,在打印機上是一個點(1/72英寸)。
邏輯QPainter坐標(biāo)到物理QPaintDevice坐標(biāo)的映射是由QPainter的轉(zhuǎn)換矩陣、視口和 “窗口” 處理的。邏輯坐標(biāo)系統(tǒng)和物理坐標(biāo)系統(tǒng)默認(rèn)重合。QPainter還支持坐標(biāo)變換(例如旋轉(zhuǎn)和縮放)。
1. 渲染
1. 邏輯表示
圖形基元的大小(寬度和高度)總是對應(yīng)于它的數(shù)學(xué)模型,而忽略渲染時使用的筆的寬度:
2. 非反鋸齒繪畫
繪制時,像素渲染由QPainter::Antialiasing渲染參數(shù)控制。
RenderHint枚舉用于指定QPainter的標(biāo)志,任何給定的引擎都可能使用這些標(biāo)志,也可能不使用。QPainter::Antialiasing值表示如果可能的話,引擎應(yīng)該消除圖元的邊緣,即通過使用不同的顏色強度平滑邊緣。
但默認(rèn)情況下,painter是帶鋸齒渲染的的,并且適用其他規(guī)則:當(dāng)使用單像素寬的筆渲染時,像素將被渲染到數(shù)學(xué)定義的點的右側(cè)和下方。例如:
當(dāng)使用偶數(shù)像素的筆進行渲染時,像素將圍繞數(shù)學(xué)定義的點進行對稱渲染,而使用奇數(shù)像素的筆進行渲染時,空閑像素將被渲染到數(shù)學(xué)點的右側(cè)和下方,就像 1 像素的情況一樣。具體的例子請參見下面的QRectF圖。
請注意,由于歷史原因,QRect::right()和QRect::bottom()函數(shù)的返回值偏離了矩形的真正右下角。
QRect的right()函數(shù)返回left() + width() - 1,而 bottom()函數(shù)返回 top() + height() - 1。上圖中的綠色點顯示了這些函數(shù)的返回坐標(biāo)。
我們建議你直接使用QRectF: QRectF類使用浮點坐標(biāo)在平面中定義一個矩形來保證精度(QRect使用整數(shù)坐標(biāo)),而QRectF::right()和QRectF::bottom()函數(shù)則返回真正的右下角。
或者,使用QRect,應(yīng)用x() + width()和y() + height()來找到右下角,避免使用right()和bottom()函數(shù)。
3. 反鋸齒的繪畫
如果你設(shè)置了QPainter的反鋸齒渲染提示,像素將在數(shù)學(xué)定義點的兩側(cè)對稱渲染:
4. 轉(zhuǎn)換
默認(rèn)情況下,QPainter在關(guān)聯(lián)設(shè)備自己的坐標(biāo)系統(tǒng)上操作,但它也完全支持仿射坐標(biāo)變換。
我們可以使用QPainter::scale()函數(shù)按給定的偏移量縮放坐標(biāo)系統(tǒng),我們可以使用QPainter::rotate()函數(shù)順時針旋轉(zhuǎn)它,并且可以使用QPainter::translate()函數(shù)平移它(即向點添加給定的偏移量)。
你也可以使用QPainter::shear()函數(shù)圍繞原點旋轉(zhuǎn)坐標(biāo)系統(tǒng)。所有的轉(zhuǎn)換操作都是在QPainter的轉(zhuǎn)換矩陣上進行的,你可以使用QPainter::worldTransform()函數(shù)來獲取這個矩陣。矩陣將平面上的一個點變換為另一個點。
如果你需要反復(fù)使用相同的變換,你也可以使用 QTransform 對象以及 QPainter::worldTransform() 和 QPainter::setWorldTransform() 函數(shù)。你可以在任何時候通過調(diào)用 QPainter::save() 函數(shù)來保存 QPainter 的轉(zhuǎn)換矩陣,該函數(shù)將矩陣保存在內(nèi)部堆棧上。QPainter::restore() 函數(shù)彈出它。
在各種繪圖設(shè)備上重用相同的繪圖代碼時,經(jīng)常需要轉(zhuǎn)換矩陣。如果沒有變換,結(jié)果將與繪制設(shè)備的分辨率緊密綁定。打印機的分辨率很高,例如每英寸600點,而屏幕的分辨率通常在每英寸72到100點之間。
Analog Clock示例展示了如何使用QPainter的轉(zhuǎn)換矩陣?yán)L制自定義控件的內(nèi)容。
我們建議在進一步閱讀之前編譯并運行此示例。特別是,嘗試將窗口大小調(diào)整為不同的大小。
void AnalogClockWindow::render(QPainter *p)
{
static const QPoint hourHand[3] = {
QPoint(7, 8),
QPoint(-7, 8),
QPoint(0, -40)
};
static const QPoint minuteHand[3] = {
QPoint(7, 8),
QPoint(-7, 8),
QPoint(0, -70)
};
QColor hourColor(127, 0, 127);
QColor minuteColor(0, 127, 127, 191);
p->setRenderHint(QPainter::Antialiasing);
p->translate(width() / 2, height() / 2);
int side = qMin(width(), height());
p->scale(side / 200.0, side / 200.0);
我們轉(zhuǎn)換坐標(biāo)系統(tǒng),使點(0,0)位于控件的中心,而不是位于左上角。我們還按邊/ 100縮放系統(tǒng),邊是控件的寬度或高度,以最短的為準(zhǔn)。我們希望時鐘是方的,即使設(shè)備不是方的。
這將給我們一個200 × 200的正方形區(qū)域,原點(0,0)在中心,我們可以在上面繪圖。我們繪制的內(nèi)容將顯示在適合控件的最大可能的正方形中。
另請參見窗口-視口轉(zhuǎn)換部分。
QTime time = QTime::currentTime();
p->save();
p->rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
p->drawConvexPolygon(hourHand, 3);
p->restore();
我們通過旋轉(zhuǎn)坐標(biāo)系并調(diào)用QPainter::drawConvexPolygon()來繪制時鐘的時針。由于旋轉(zhuǎn),它被畫在了正確的方向上。
多邊形被指定為一個交替的x, y值數(shù)組,存儲在hourHand靜態(tài)變量中(在函數(shù)開始處定義),它對應(yīng)于四個點(2,0),(0,2),(- 2,0)和(0,-25)。
對代碼周圍的 QPainter::save() 和 QPainter::restore() 的調(diào)用保證了后面的代碼不會受到我們使用的轉(zhuǎn)換的干擾。
p->save();
p->rotate(6.0 * (time.minute() + time.second() / 60.0));
p->drawConvexPolygon(minuteHand, 3);
p->restore();
我們對時鐘的分針也是這樣做的,分針由四個點 (1,0)、(0,1)、(- 1,0) 和 (0,-40) 定義。這些坐標(biāo)指定了一個比分針更細(xì)更長的指針。
p->setPen(minuteColor);
for (int j = 0; j < 60; ++j) {
if ((j % 5) != 0)
p->drawLine(92, 0, 96, 0);
p->rotate(6.0);
}
最后,我們繪制時鐘面,它由12條30度間隔的短線組成。
Window-Viewport轉(zhuǎn)換
當(dāng)使用QPainter繪圖時,我們使用邏輯坐標(biāo)指定點,然后將其轉(zhuǎn)換為繪制設(shè)備的物理坐標(biāo)。
邏輯坐標(biāo)到物理坐標(biāo)的映射是由QPainter的世界變換 worldTransform() (在變換部分描述)和 QPainter 的 viewport() 和 window() 處理的。視口表示指定任意矩形的物理坐標(biāo)?!按翱凇痹谶壿嬜鴺?biāo)中描述相同的矩形。默認(rèn)情況下,邏輯和物理坐標(biāo)系統(tǒng)是重合的,相當(dāng)于繪制設(shè)備的矩形。
使用窗口-視口轉(zhuǎn)換,我們可以使邏輯坐標(biāo)系統(tǒng)符合我們的偏好。所述還可用于使所述繪圖代碼獨立于所述QPaintDevice 。例如,你可以通過調(diào)用QPainter::setwinwindow()函數(shù),使邏輯坐標(biāo)從(-50,-50)擴展到(50,50),中間是(0,0):
QPainter painter(this);
painter.setWindow(QRect(-50, -50, 100, 100));
現(xiàn)在,邏輯坐標(biāo)(-50,-50)對應(yīng)于繪制設(shè)備的物理坐標(biāo)(0,0)。獨立于繪制設(shè)備,我們的繪制代碼將始終對指定的邏輯坐標(biāo)進行操作。相當(dāng)于我們可以手動的設(shè)置這種坐標(biāo)關(guān)系。自己定義這種坐標(biāo)的方便關(guān)系。
通過設(shè)置“窗口”或視口矩形,可以執(zhí)行坐標(biāo)的線性變換。請注意,“窗口”的每個角落都映射到viewport的相應(yīng)角落,反之亦然。出于這個原因,讓視口和“窗口”保持相同的寬高比以防止變形通常是一個好主意:
int side = qMin(width(), height())
int x = (width() - side / 2);
int y = (height() - side / 2);
painter.setViewport(x, y, side, side);
如果我們將邏輯坐標(biāo)系統(tǒng)設(shè)置為正方形,我們也應(yīng)該使用QPainter::setViewport()函數(shù)將視口設(shè)置為正方形。在上面的例子中,我們將其設(shè)置為適合繪制設(shè)備矩形的最大正方形。通過在設(shè)置窗口或視口時考慮繪制設(shè)備的大小,可以保持繪制代碼獨立于繪制設(shè)備。
請注意,窗口-視口轉(zhuǎn)換只是一個線性轉(zhuǎn)換,即它不執(zhí)行裁剪。這意味著如果你在當(dāng)前設(shè)置的“窗口”之外繪制,你的繪畫仍然會使用相同的線性代數(shù)方法轉(zhuǎn)換到視口。
視口、“窗口” 和 變換矩陣 決定了邏輯QPainter坐標(biāo)如何映射到繪制設(shè)備的物理坐標(biāo)。默認(rèn)情況下,世界變換矩陣是單位矩陣,“窗口”和視口設(shè)置等同于繪制設(shè)備的設(shè)置,即世界、“窗口”和設(shè)備坐標(biāo)系是等效的,但正如我們所看到的,系統(tǒng)可以使用轉(zhuǎn)換操作和窗口-視口轉(zhuǎn)換來操縱。
五、讀寫圖像文件
讀取圖像最常見的方法是通過QImage和QPixmap的構(gòu)造函數(shù),或者調(diào)用QImage::load()和QPixmap::load()函數(shù)。此外,Qt提供了QImageReader類,它提供了對進程的更多控制。根據(jù)圖像格式的底層支持,類提供的函數(shù)可以節(jié)省內(nèi)存并加快圖像加載速度。
同樣,Qt提供了QImageWriter類,它支持在存儲圖像之前設(shè)置特定格式的選項,如伽馬值、壓縮級別和質(zhì)量。如果我們不需要這些選項,我們可以使用QImage::save()或QPixmap::save()代替。
1. QMovie
QMovie是一個用于顯示動畫的方便類,在內(nèi)部使用QImageReader類。創(chuàng)建后,QMovie類為運行和控制給定動畫提供了各種函數(shù)。文章來源:http://www.zghlxwxcb.cn/news/detail-650171.html
QImageReader和QImageWriter類依賴于QImageIOHandler類,QImageIOHandler類是Qt中所有圖像格式的通用圖像I/O接口,QImageReader和QImageWriter內(nèi)部使用QImageIOHandler對象來為Qt添加對不同圖像格式的支持。
QImageReader::supportedImageFormats()和QImageWriter::supportedImageFormats()函數(shù)提供了支持的文件格式列表。Qt默認(rèn)支持幾種文件格式,此外還可以通過插件添加新格式。目前支持的格式在QImageReader和QImageWriter類文檔中列出。
Qt的插件機制也可以用來編寫自定義圖像格式處理程序。這是通過從QImageIOHandler類派生,并創(chuàng)建一個QImageIOPlugin對象來完成的,該對象是創(chuàng)建QImageIOHandler對象的工廠。當(dāng)插件安裝后,QImageReader和QImageWriter會自動加載插件并開始使用它。文章來源地址http://www.zghlxwxcb.cn/news/detail-650171.html
六、繪圖相關(guān)設(shè)備
Paint 相關(guān) | 功能 |
---|---|
QBitmap | 單色(1位深度)像素圖 |
QBrush | 定義由QPainter繪制的形狀的填充模式 |
QColor | 基于RGB、HSV或CMYK值的顏色 |
QColorSpace | 色彩空間抽象 |
QColorTransform | 顏色空間之間的轉(zhuǎn)換 |
QColormap | 將獨立于設(shè)備的QColors映射到依賴于設(shè)備的像素值 |
QConicalGradient | 與QBrush組合使用指定一個錐形梯度刷 |
QFont | 指定用于繪制文本的字體查詢 |
QFontMetrics | 字體度量信息 |
QFontMetricsF | 字體度量信息 |
QGenericMatrix | 表示N列M行NxM變換矩陣的模板類 |
QGradient | 與QBrush組合使用來指定梯度填充 |
QIcon | 可伸縮的圖標(biāo)在不同的模式和狀態(tài) |
QIconEngine | QIcon渲染器的抽象基類 |
QImage | 獨立于硬件的圖像表示,允許直接訪問像素數(shù)據(jù),并可以用作繪制設(shè)備 |
QImageReader | 格式獨立接口,用于從文件或其他設(shè)備讀取圖像 |
QImageWriter | 格式獨立接口,用于將圖像寫入文件或其他設(shè)備 |
QLine | 使用整數(shù)精度的二維向量 |
QLineF | 二維向量使用浮點精度 |
QLinearGradient | 與QBrush組合使用來指定一個線性梯度刷 |
QMargins | 定義矩形的四個邊距 |
QMarginsF | 定義矩形的四個邊距 |
QPagedPaintDevice | 表示支持多個頁面的繪制設(shè)備 |
QPaintDevice | 可以用QPainter繪制的對象的基類 |
QPaintEngine | QPainter如何在給定平臺上繪制到給定設(shè)備的抽象定義 |
QPainter | 在部件和其他繪制設(shè)備上執(zhí)行低級繪制 |
QPainterPath | 用于繪制操作的容器,使圖形能夠被構(gòu)建和重用 |
QPainterPathStroker | 用于為給定的繪制路徑生成可填充的輪廓 |
QPdfWriter | 類以生成可用作繪圖設(shè)備的pdf |
QPen | 定義一個QPainter應(yīng)該如何繪制線條和形狀的輪廓 |
QPixmap | 可以用作繪畫設(shè)備的屏幕外圖像表示 |
QPoint | 使用整數(shù)精度定義平面中的一個點 |
QPointF | 在平面中使用浮點精度定義一個點 |
QPolygon | 使用整數(shù)精度的點向量 |
QPolygonF | 使用浮點精度的點向量 |
QRadialGradient | 使用組合與QBrush指定一個徑向梯度刷 |
QRect | 使用整數(shù)精度在平面內(nèi)定義一個矩形 |
QRectF | 在平面中使用浮點精度定義一個矩形 |
QRegion | 指定繪制器的剪輯區(qū)域 |
QRgba64 | Struct包含64位RGB顏色 |
QSize | 使用整數(shù)點精度定義二維對象的大小 |
QSizeF | 使用浮點精度定義二維對象的大小 |
QStylePainter | 用于在窗口組件中繪制QStyle元素的便利類 |
QSupportedWritingSystems | 在使用內(nèi)部Qt fontdatabase注冊字體時使用 |
QSvgGenerator | 用于創(chuàng)建SVG繪圖的繪圖設(shè)備 |
QSvgRenderer | 用于將SVG文件的內(nèi)容繪制到繪圖設(shè)備上 |
QSvgWidget | 用于顯示可伸縮矢量圖形(SVG)文件內(nèi)容的控件 |
QTransform | 指定坐標(biāo)系統(tǒng)的2D變換 |
QVector2D | 表示二維空間中的向量或頂點 |
到了這里,關(guān)于Qt掃盲-Qt Paint System 概述的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!