绘图和绘图设备
繪圖和繪圖設備
文章目錄
- 繪圖和繪圖設備
- 一、QPainter
- 二. 繪圖設備
- 三. 手動更新窗口
- 四. QPixmap、QBitmap、QImage
- 五. QPicture
一、QPainter
1. Qt 的繪圖系統允許使用相同的 API 在屏幕和其它打印設備上進行繪制。整個繪圖系統基于QPainter,QPainterDevice和QPaintEngine三個類。
- QPainter用來執行繪制的操作;
- QPaintDevice是一個二維空間的抽象,這個二維空間允許QPainter在其上面進行繪制,也就是QPainter工作的空間;
- QPaintEngine提供了畫筆(QPainter)在不同的設備上進行繪制的統一的接口。QPaintEngine類應用于QPainter和QPaintDevice之間,通常對開發人員是透明的。除非你需要自定義一個設備,否則你是不需要關心QPaintEngine這個類的。我們可以把QPainter理解成畫筆;把QPaintDevice理解成使用畫筆的地方,比如紙張、屏幕等;而對于紙張、屏幕而言,肯定要使用不同的畫筆繪制,為了統一使用一種畫筆,我們設計了QPaintEngine類,這個類讓不同的紙張、屏幕都能使用一種畫筆。
下圖給出了這三個類之間的層次結構:
上面的示意圖告訴我們,Qt 的繪圖系統實際上是,使用QPainter在QPainterDevice上進行繪制,它們之間使用QPaintEngine進行通訊(也就是翻譯QPainter的指令)。
2. paintEvent函數
[virtual protected] void QWidget::paintEvent(QPaintEvent *event)作用:可以在子類中重新實現此事件處理程序,以接收在事件中傳遞的繪圖事件。 如果在窗口繪圖,必須放在繪圖事件內實現,繪圖事件自動調用
3. QPainter函數
QPainter::QPainter(QPaintDevice *device)作用:構造一個立即開始繪畫的畫家的繪畫裝置。
4.drawPixmap函數
void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)作用:在繪制設備中,將給定像素圖的矩形部分源繪制到給定目標中。注意:如果像素圖和矩形大小不一致,像素圖會縮放以適應矩形。
5.drawLine函數
void QPainter::drawLine(int x1, int y1, int x2, int y2)作用:這是一個重載函數。畫一條從(x1, y1)到(x2, y2)的直線。
6.setWidth函數
void QPen::setWidth(int width)作用:將筆寬度設置為給定寬度(以像素為單位,精度為整數)。線寬為0表示化妝筆。這意味著筆寬度總是繪制一個像素寬,獨立于畫家設置的轉換。不支持設置帶負值的鋼筆寬度。
7.setColor函數
void QPen::setColor(const QColor &color)作用:將筆的顏色設置為給定的顏色
8.setStyle函數
void QPen::setStyle(Qt::PenStyle style)作用:將筆樣式設置為給定的樣式
9.drawRect函數
void QPainter::drawRect(const QRectF &rectangle)作用:畫矩形
10.drawEllipse函數
void QPainter::drawEllipse(const QRectF &rectangle)作用:畫圓形
#include "widget.h" #include "ui_widget.h" #include <QPainter> #include <QPen> #include <QBrush>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }void Widget::paintEvent(QPaintEvent *event) {//定義一個畫家的兩種方式//1. QPainter p(this);//2.begin和endQPainter p;p.begin(this);//相當于放了一個背景圖片//p.drawPixmap(0,0,width(),height(),QPixmap("../1.JPG"));//p.drawPixmap(rect(),QPixmap("../1.JPG"));//創建一個畫筆QPen pen;//定義畫筆的寬度pen.setWidth(5);//設置畫筆的顏色//pen.setColor(Qt::red);pen.setColor(QColor(14,9,234));//設置畫筆的樣式pen.setStyle(Qt::DashLine);//把畫筆交給畫家p.setPen(pen);//定義一個填充顏色的對象(油漆桶)QBrush brush;//設定填充的顏色brush.setColor(QColor(Qt::red));//設定填充的樣式brush.setStyle(Qt::SolidPattern);//把油漆桶交給畫家p.setBrush(brush);//畫直線p.drawLine(50,50,150,50);p.drawLine(50,50,50,150);p.drawLine(150,50,150,150);p.drawLine(150,150,50,150);//畫矩陣p.drawRect(200,200,200,200);//畫圓p.drawEllipse(QPoint(212,122),50,50);p.end(); }二. 繪圖設備
繪圖設備是指繼承QPainterDevice的子類。Qt一共提供了四個這樣的類,分別是QPixmap、QBitmap、QImage和 QPicture。其中,
- QPixmap專門為圖像在屏幕上的顯示做了優化
- QBitmap是QPixmap的一個子類,它的色深限定為1,可以使用 QPixmap的isQBitmap()函數來確定這個QPixmap是不是一個QBitmap。
- QImage專門為圖像的像素級訪問做了優化。
- QPicture則可以記錄和重現QPainter的各條命令。
三. 手動更新窗口
1.update函數
[slot] void QWidget::update()作用:更新小部件,除非禁用更新或隱藏小部件。此函數不會導致立即重繪;相反,它在Qt返回主事件循環時為處理調度一個paint事件。這允許Qt進行優化,以獲得比調用repaint()更快的速度和更少的閃爍。多次調用update()通常只會導致一次paintEvent()調用。
void Widget::paintEvent(QPaintEvent *event) {//QPainter p(this);QPainter p;p.drawPixmap(x,150,99,99,QPixmap("../1.JPG"));p.end(); }void Widget::on_pushButton_clicked() {x += 20;if(x > width()){x = 0;}//必須刷新窗口,否則達不到效果update(); }四. QPixmap、QBitmap、QImage
- QPixmap繼承了QPaintDevice,因此,你可以使用QPainter直接在上面繪制圖形。
- QPixmap也可以接受一個字符串作為一個文件的路徑來顯示這個文件,比如你想在程序之中打開png、jpeg之類的文件,就可以使用 QPixmap。
- 使用QPainter的drawPixmap()函數可以把這個文件繪制到一個QLabel、QPushButton或者其他的設備上面。
- QPixmap是針對屏幕進行特殊優化的,因此,它與實際的底層顯示設備息息相關。注意,這里說的顯示設備并不是硬件,而是操作系統提供的原生的繪圖引擎。所以,在不同的操作系統平臺下,QPixmap的顯示可能會有所差別。
- QBitmap繼承自QPixmap,因此具有QPixmap的所有特性,提供單色圖像。
- QBitmap的色深始終為1, 色深這個概念來自計算機圖形學,是指用于表現顏色的二進制的位數。我們知道,計算機里面的數據都是使用二進制表示的。為了表示一種顏色,我們也會使用二進制。比如我們要表示8種顏色,需要用3個二進制位,這時我們就說色深是3. 因此,所謂色深為1,也就是使用1個二進制位表示顏色。1個位只有兩種狀態:0和1,因此它所表示的顏色就有兩種,黑和白。所以說,QBitmap實際上是只有黑白兩色的圖像數據。
- 由于QBitmap色深小,因此只占用很少的存儲空間,所以適合做光標文件和筆刷。
- QPixmap使用底層平臺的繪制系統進行繪制,無法提供像素級別的操作
- 而QImage則是使用獨立于硬件的繪制系統,實際上是自己繪制自己,因此提供了像素級別的操作,并且能夠在不同系統之上提供一個一致的顯示形式。
- 我們聲明了一個QImage對象,大小是300 x 300,顏色模式是RGB32,即使用32位數值表示一個顏色的RGB值,也就是說每種顏色使用8位。然后我們對每個像素進行顏色賦值,從而構成了這個圖像。我們可以把QImage想象成一個RGB顏色的二維數組,記錄了每一像素的顏色。
QImage與QPixmap的區別
- QPixmap主要是用于繪圖,針對屏幕顯示而最佳化設計,QImage主要是為圖像I/O、圖片訪問和像素修改而設計的
- QPixmap依賴于所在的平臺的繪圖引擎,故例如反鋸齒等一些效果在不同的平臺上可能會有不同的顯示效果,QImage使用Qt自身的繪圖引擎,可在不同平臺上具有相同的顯示效果
- 由于QImage是獨立于硬件的,也是一種QPaintDevice,因此我們可以在另一個線程中對其進行繪制,而不需要在GUI線程中處理,使用這一方式可以很大幅度提高UI響應速度。
- QImage可通過setPixpel()和pixel()等方法直接存取指定的像素。
QImage與QPixmap之間的轉換:
QImage轉QPixmap
使用QPixmap的靜態成員函數: fromImage()
QPixmap轉QImage:
使用QPixmap類的成員函數: toImage()
五. QPicture
- 這是一個可以記錄和重現QPainter命令的繪圖設備。QPicture將QPainter的命令序列化到一個IO設備,保存為一個平臺獨立的文件格式。這種格式有時候會是“元文件(meta-files)”。Qt的這種格式是二進制的,不同于某些本地的元文件,Qt的pictures文件沒有內容上的限制,只要是能夠被QPainter繪制的元素,不論是字體還是pixmap,或者是變換,都可以保存進一個picture中。
- QPicture是平臺無關的,因此它可以使用在多種設備之上,比如svg、pdf、ps、打印機或者屏幕。回憶下我們這里所說的QPaintDevice,實際上是說可以有QPainter繪制的對象。QPicture使用系統的分辨率,并且可以調整QPainter來消除不同設備之間的顯示差異。
- 如果我們要記錄下QPainter的命令,首先要使用QPainter::begin()函數,將QPicture實例作為參數傳遞進去,以便告訴系統開始記錄,記錄完畢后使用QPainter::end()命令終止。
代碼示例如下:
void PaintWidget::paintEvent(QPaintEvent *) {QPicture pic;QPainter painter;//將圖像繪制到QPicture中,并保存到文件painter.begin(&pic);painter.drawEllipse(20, 20, 100, 50);painter.fillRect(20, 100, 100, 100, Qt::red);painter.end();pic.save("D:\\drawing.pic");//將保存的繪圖動作重新繪制到設備上pic.load("D:\\drawing.pic");painter.begin(this);painter.drawPicture(200, 200, pic);painter.end(); }總結