目錄
- 1. 繪圖基本概念
- 2. 繪制各種形狀
- 2.1 繪制線段
- 2.2 繪制矩形
- 2.3 繪制圓形
- 2.4 繪制文本
- 2.5 設置畫筆
- 2.6 設置畫刷
- 3. 繪制圖片
- 3.1 繪制簡單圖片
- 3.2 平移圖片
- 3.3 縮放圖片
- 3.4 旋轉圖片
- 4. 其他設置
- 4.1 移動畫家位置
- 4.2 保存/加載畫家的狀態
- 5. 特殊的繪圖設備
- 5.1 QPixmap
- 5.2 QImage
- 5.3 QPicture
- 6. 其他話題
1. 繪圖基本概念
(1)雖然 Qt 已經內置了很多的控件,但是不能保證現有控件就可以應對所有場景。
- 很多時候我們需要更強的 “自定制” 能力。
- Qt 提供了畫圖相關的 API,可以允許我們在窗口上繪制任意的圖形形狀,來完成更復雜的界面設計。
(2)所謂的 “控件”,本質上也是通過畫圖的方式畫上去的。
- 畫圖 API 和 控件 之間的關系,可以類比成機器指令和高級語言之間的關系。
- 控件是對畫圖 API 的進?步封裝;畫圖 API 是控件的底層實現。
(3)繪圖 API 核心類。
類 | 說明 |
---|---|
QPainter | “繪畫者” 或者 “畫家”。用來繪圖的對象,提供了?系列 drawXXX 方法,可以允許我們繪制各種圖形。 |
QPaintDevice | “畫板”。描述了 QPainter 把圖形畫到哪個對象上。像咱們之前用過的 QWidget 也是?種 QPaintDevice (QWidget 是 QPaintDevice 的子類)。 |
QPen | “畫筆”。描述了 QPainter 畫出來的線是什么樣的。 |
QBrush | “畫刷”。描述了 QPainter 填充?個區域是什么樣的。 |
(4)繪圖 API 的使用一般不會在 QWidget 的構造函數中使用,而是要放到 paintEvent 事件中。關于 paintEvent:
- paintEvent 會在以下情況下被觸發:
- 控件首次創建。
- 控件被遮擋,再解除遮擋。
- 窗口最小化,再恢復。
- 窗口最小化,再恢復。
- 控件大小發生變化時。
- 主動調用 repaint() 或者 update() 方法。(這兩個方法都是 QWidget 的方法)。
- …
- 因此,如果把繪圖 api 放到構造函數中調用,那么?旦出現上述的情況,界面的繪制效果就無法確保符合預期了。
2. 繪制各種形狀
2.1 繪制線段
(1)示例1:
void drawLine(const QPoint &p1, const QPoint &p2);
- 參數:
- p1:繪制起點坐標。
- p2:繪制終點坐標。
- 在 “widget.h” 頭文件中聲明繪圖事件;
- 在 “widget.cpp” 文件中重寫 paintEvent() 方法;
- 實現效果如下:
(2)示例2:
void drawLine ( int x1, int y1, int x2, int y2 );
- 參數:
- x1,y1:繪制起點坐標。
- x2,y2:繪制終點坐標。
2.2 繪制矩形
(1)函數原型:
void QPainter::drawRect(int x, int y, int width, int height);
- 參數:
- x:窗口橫坐標;
- y:窗口縱坐標;
- width:所繪制矩形的寬度;
- height:所繪制矩形的高度;
(2)示例:
2.3 繪制圓形
(1)函數原型:
void QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
- 參數:
- center:中心點坐標;
- rx:橫坐標;
- ry:縱坐標;
(2)示例:
- 實現效果:
2.4 繪制文本
(1)QPainter類 中不僅提供了繪制圖形的功能,還可以使用 QPainter::drawText() 函數來繪制文字,也可以使用QPainter::setFont() 設置字體等信息。示例:
- 實現效果如下:
2.5 設置畫筆
(1)QPainter 在繪制時,是有?個默認的畫筆的。在使用時也可以自定義畫筆。在 Qt 中,QPen類中定義了 QPainter 應該如何繪制形狀、線條和輪廓。同時通過 QPen類 可以設置畫筆的線寬、顏色、樣式、畫刷等。
- 畫筆的顏色可以在實例化畫筆對象時進行設置,畫筆的寬度是通過 setWidth() 方法進行設置,畫筆的風格是通過setStyle()方法進行設置,設置畫刷主要是通過 setBrush() 方法。
- 設置畫筆顏色:QPen::QPen(const QColor &color); 畫筆的顏色主要是通過 QColor 類設置;
- 設置畫筆寬度:void QPen::setWidth(int width);
- 設置畫筆風格:void QPen::setStyle(Qt::PenStyle style);
(2)畫筆的風格有:
(3)示例:畫筆的使用。
- 實現效果如下:
2.6 設置畫刷
(1)在 Qt 中,畫刷是使用 QBrush類 來描述,畫刷大多用于填充。QBrush定義了QPainter的填充模式,具有樣式、顏色、漸變以及紋理等屬性。
- 畫刷的格式中定義了填充的樣式,使用 Qt::BrushStyle 枚舉,默認值是 Qt::NoBrush,也就是不進行任何填充。可以通過 Qt 助手查找畫刷的格式。如下圖示:
- 設置畫刷主要通過 void QPen::setBrush(const QBrush &brush) 方法,其參數為畫刷的格式。
(2)示例:
- 實現效果:
3. 繪制圖片
(1)Qt 提供了四個類來處理圖像數據:QImage、QPixmap、QBitmap 和 QPicture,它們都是常用的繪圖設備。
- 其中QImage主要用來進行 I/O 處理,它對 I/O 處理操作進行了優化,而且可以用來直接訪問和操作像素;QPixmap 主要用來在屏幕上顯示圖像,它對在屏幕上顯示圖像進行了優化;QBitmap 是 QPixmap 的子類,用來處理顏色深度為1的圖像,即只能顯示黑白兩種顏色;QPicture 用來記錄并重演 QPainter 命令。這?節只講解 QPixmap。
3.1 繪制簡單圖片
(1)新建 Qt 項目,基類選擇 QWidget,項目名稱為 QPainter。在 “widget.h” 頭文件中聲明繪畫事件;如下圖示:
- 添加資源文件;首先準備?些圖片資源文件,并將這些圖片資源文件放在同?個文件夾中,將該文件夾復制到本項目中。
- 選中項目文件,鼠標右鍵 -------> add new… 。
- 點擊 “add new…” 之后,出現如下界面:
- 選擇 “Choose…” 之后,給資源文件命名;
- 點擊 “下?步”,出現如下界面,點擊 “完成”;
- 給資源文件添加前綴,并將資源文件添加至項目中;
- 將所有的資源文件添加到項目中,方便后續使用;
- 點擊 “構建并運行” 按鈕,將資源文件添加到項目中;
- 在 “widget.cpp” 文件中實現畫圖片功能;
- 實現效果如下:
3.2 平移圖片
(1)平移圖片實際是通過改變坐標來實現。QPainter類中提供了 translate()函數 來實現坐標原點的改變。如下示例:
- 實現效果如下:
3.3 縮放圖片
(1)在 Qt 中,圖片的放大和縮小可以使用 QPainter類 中的 drawPixmap()函數 來實現。示例:
- 實現效果如下:
3.4 旋轉圖片
(1)圖片的旋轉使用的是 QPainter類 中的 rotate()函數,它默認是以原點為中心進行旋轉的。如果要改變旋轉的中心,可以使用 translate()函數 完成。示例:
- 實現效果如下:
4. 其他設置
4.1 移動畫家位置
(1)有時候在繪制多個圖形時,想使用同一坐標位置,那么繪制出來的圖形肯定會重合,此時,可以通過移動畫家的位置來使圖形不發生重合。
- 示例1:未移動畫家位置。
- 實現效果如下:
- 示例2:移動畫家位置。使用 translate 移動畫家所在位置:
- 實現效果如下:
4.2 保存/加載畫家的狀態
(1)在繪制圖形的過程中,可以通過 save() 函數來保存畫家的狀態,使用 restore() 函數還原畫家狀態。
- save() 函數原型如下:
void QPainter::save();
- restore() 函數原型如下:
void QPainter::restore();
(2)示例:
- 實現效果如下:
(3)說明:
- 上述示例中,在畫第三個圓之前,由于還原了畫家的狀態,所以此時畫家的位置坐標會移動到畫家狀態保存的地方,所以在繪制第三個圓的位置時實際是和第?個圓發生了重疊。
5. 特殊的繪圖設備
(1)前面的代碼中我們是使用 QWidget 作為繪圖設備。在 Qt 中還存在下列三個比較特殊的繪圖設備。此處我們也簡要介紹。
- QPixmap 用于在顯示器上顯示圖片。
- QImage 用于對圖片進行像素級修改。
- QPicture 用于對 QPainter 的?系列操作進行存檔。
5.1 QPixmap
(1)QPixmap 核心特性:
- 使用 QPainter 直接在上面進行繪制圖形。
- 通過文件路徑加載并顯示圖片。
- 搭配 QPainter 的 drawPixmap()函數,可以把這個圖片繪制到?個 QLabel、QPushButton 等控件上。
- 和系統/顯示設備強相關,不同系統/顯示設備下,QPixmap 的顯示可能會有所差別。
(2)示例:
- 實現效果:
5.2 QImage
(1)QImage 的核心特性:
- 使用 QPainter 直接在上面進行繪制圖形。
- 通過文件路徑加載并顯示圖片。
- 能夠針對圖片進行像素級別的操作(操作某個指定的像素)。
- 獨立于硬件的繪制系統,能夠在不同系統之上提供?致的顯示。
(2)代碼示例:QImage 作為繪圖設備的使用。
(3)代碼示例:QImage 繪圖時對像素的修改。
- 新建 Qt 項目,添加圖片資源文件到項目中;如下圖示:
- 在 widget.h 頭文件中聲明繪圖事件;
- 在 widget.cpp 文件中重寫繪圖事件,使用 QImage 對圖片像素進行修改;
- 通過 setPixel 設置某個像素的顏色值。
- 使用 qRgb 表示?個具體的顏色。
- 執行效果如下:
- 沒有修改像素之前:
- 修改像素之后:
5.3 QPicture
(1)QPicture 核心特性:
- 使用 QPainter 直接在上面進行繪制圖形。
- 通過文件路徑加載并顯示圖片。
- 能夠記錄 QPainter 的操作步驟。
- 獨立于硬件的繪制系統,能夠在不同系統之上提供?致的顯示。
(2)注意:
QPicture 加載的必須是自身的存檔文件,而不能是任意的 png, jpg 等圖片文件。
(3)QPicture 類似于很多游戲的 Replay 功能。
- 例如像 war3 這樣的經典游戲,即使是?場 60 分鐘的膀胱局,生成的 replay 文件,也不過幾百個 KB。
- 此處的 Replay 功能并非是把整個游戲畫面都錄制保存下來,而是記錄了地圖中發生的所有事件(地圖元素,玩家單位操作,中立生物行為等…)。
- 當回放 Replay 的時候其實就是把上述記錄的事件再?條?條的執行?遍即可還原之前的游戲場景了。
- 不了解游戲的也可以理解成警察錄筆錄,并通過筆錄還原案發現場。
(4)如果要記錄下 QPainter 的命令,首先要使用 QPainter::begin() 函數,將 QPicture 實例作為參數傳遞進去,以便告訴系統開始記錄,記錄完畢后使用 QPainter::end() 命令終至。如下示例:
- 實現效果:
- 通過 QPicture 重現繪圖指令后,實現的效果如下:
6. 其他話題
(1)Qt 中對于界面的優化美化,還涉及到很多其他的話題。
- Qt 動畫 。
- Qt 3D 圖形 。
- QQuick 。
- 使用第三方控件庫。
- Qt Design Studio 。
- …
(2)Qt 的QSS介紹見博客:https://blog.csdn.net/m0_65558082/article/details/147787398?spm=1001.2014.3001.5502