/*******************************************************************************************/
一、繪圖
整個繪圖系統基於QPainter,QPainterDevice和QPaintEngine三個類:
QPainter(畫家)->QPaintEngine(中間引擎,畫家與設備之間的交互(通信接口),對於應用開發一般用不上)->QpaintDevice(設備,表示畫在哪里)
畫圖的時候就是要重寫事件:
protected:
//重寫繪圖事件,虛函數
//如果在窗口上(給窗口)繪圖,必須放在繪圖事件里實現
//繪圖事件內部自動調用,窗口需要重繪的時候(窗口狀態改變的時候)自動調用
//當然也可以人為的調用
void paintEvent(QPaintEvent *);
void Widget::paintEvent(QPaintEvent *)
{
//QPainter p(this);//這是一種方法,因為this是Widget也是一種繪圖設備
//另一種方法,begin
QPainter p;//創建畫家對象
p.begin(this);//指定當前窗口為繪圖設備,因為this是Widget也是一種繪圖設備
//繪圖操作
//p.drawxxx();
//比如,畫背景圖(一般先畫):
//p.drawPixmap(0, 0, width(), height(), QPixmap("../Image/bk.png")); //繪圖操作
p.drawPixmap(rect(), QPixmap("../Image/bk.png"));
//定義畫筆,畫筆確定畫家畫出什么樣的效果
QPen pen;
pen.setWidth(5); //設置線寬大小,
//pen.setColor(Qt::red); //設置顏色
pen.setColor( QColor(14, 9, 234) );//rgb設置顏色
pen.setStyle(Qt::DashLine); //設置風格
//把畫筆交給畫家,這樣畫家才有畫筆,才生效
p.setPen(pen);
//畫直線
p.drawLine(50, 50, 150, 50);
p.drawLine(50, 50, 50, 150);
//創建畫刷對象,用於封閉圖形填充顏色
QBrush brush;
brush.setColor(Qt::red); //設置顏色
brush.setStyle(Qt::Dense1Pattern);//設置樣式
//把畫刷交給畫家
p.setBrush(brush);
//畫矩形
p.drawRect(150, 150, 100, 50);
//畫圓形,后兩個分別是水平半徑和垂直半徑,當相等的時候為圓形
p.drawEllipse(QPoint(150, 150), 50, 25);
//畫笑臉
p.drawPixmap(x, 180, 80, 80, QPixmap("../Image/face.png"));
//另一種方法,end
p.end();
/*******************************************************************************************/
二、手動更新窗口
調用update()函數:
void Widget::on_pushButton_clicked()
{
x += 20;
if(x > width())
{
x = 0;
}
//刷新窗口,讓窗口重繪,沒有參數所以整個窗口都刷新(重繪),如果有填入指定區域的參數,則只刷新區域部分
update(); //相當於間接調用paintEvent()
}
上述代碼具體見《PaintEvent》

1 #ifndef WIDGET_H 2 #define WIDGET_H 3 4 #include <QWidget> 5 6 namespace Ui { 7 class Widget; 8 } 9 10 class Widget : public QWidget 11 { 12 Q_OBJECT 13 14 public: 15 explicit Widget(QWidget *parent = 0); 16 ~Widget(); 17 18 protected: 19 //重寫繪圖事件,虛函數 20 //如果在窗口繪圖,必須放在繪圖事件里實現 21 //繪圖事件內部自動調用,窗口需要重繪的時候(狀態改變) 22 void paintEvent(QPaintEvent *); 23 24 private slots: 25 void on_pushButton_clicked(); 26 27 private: 28 Ui::Widget *ui; 29 int x; 30 }; 31 32 #endif // WIDGET_H

1 #include "widget.h" 2 #include "ui_widget.h" 3 #include <QPainter> 4 #include <QPen> 5 #include <QBrush> 6 7 Widget::Widget(QWidget *parent) : 8 QWidget(parent), 9 ui(new Ui::Widget) 10 { 11 ui->setupUi(this); 12 13 x = 0; 14 } 15 16 Widget::~Widget() 17 { 18 delete ui; 19 } 20 21 void Widget::paintEvent(QPaintEvent *) 22 { 23 //QPainter p(this); 24 25 QPainter p;//創建畫家對象 26 p.begin(this);//指定當前窗口為繪圖設備 27 28 //繪圖操作 29 //p.drawxxx(); 30 //畫背景圖 31 //p.drawPixmap(0, 0, width(), height(), QPixmap("../Image/bk.png")); 32 p.drawPixmap(rect(), QPixmap("../Image/bk.png")); 33 34 //定義畫筆 35 QPen pen; 36 pen.setWidth(5); //設置線寬 37 //pen.setColor(Qt::red); //設置顏色 38 pen.setColor( QColor(14, 9, 234) );//rgb設置顏色 39 pen.setStyle(Qt::DashLine); //設置風格 40 41 //把畫筆交給畫家 42 p.setPen(pen); 43 44 //畫直線 45 p.drawLine(50, 50, 150, 50); 46 p.drawLine(50, 50, 50, 150); 47 48 //創建畫刷對象 49 QBrush brush; 50 brush.setColor(Qt::red); //設置顏色 51 brush.setStyle(Qt::Dense1Pattern);//設置樣式 52 53 //把畫刷交給畫家 54 p.setBrush(brush); 55 56 57 //畫矩形 58 p.drawRect(150, 150, 100, 50); 59 60 //畫圓形 61 p.drawEllipse(QPoint(150, 150), 50, 25); 62 63 //畫笑臉 64 p.drawPixmap(x, 180, 80, 80, QPixmap("../Image/face.png")); 65 66 p.end(); 67 } 68 69 void Widget::on_pushButton_clicked() 70 { 71 x += 20; 72 if(x > width()) 73 { 74 x = 0; 75 } 76 77 //刷新窗口,讓窗口重繪,整個窗口都刷新 78 update(); //間接調用paintEvent() 79 }
/*******************************************************************************************/
三、QBitMap和QPixmap的區別
QBitMap是QPixmap的子類
QBitMap是黑白的圖片
QPixmap是彩色的圖片
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QBitmap>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter p(this);
//QPixmap 圖片背景透明
p.drawPixmap(0, 0, QPixmap("../Image/butterfly.png"));
//QBitmap 圖片背景透明 透明的部分變為黑色了
p.drawPixmap(200, 0, QBitmap("../Image/butterfly.png"));
//QPixmap 圖片背景白色
QPixmap pixmap;
pixmap.load("../Image/butterfly1.png");
p.drawPixmap(0, 200, pixmap);
//QBitmap 圖片背景白色,白色變為透明了
QBitmap bitmap;
bitmap.load("../Image/butterfly1.png");
p.drawPixmap(200, 200, bitmap);
}
/*******************************************************************************************/
四、繪圖設備
繪圖設備主要有三種:
I、QPixmap //最常用,針對屏幕進行優化了,和平台(顯卡)相關,不可以對圖片進行修改 //QBitMap是QPixmap的子類 QBitMap是黑白的圖片
II、QImage //沒有優化,和平台無關,有自己的一套系統。可以對圖片進行修改(像素點的修改),可以在線程中繪圖即可以在單獨開的線程中使用
III、QPicture //平台無關的,保存繪圖的狀態(保存為一個二進制文件),可以給另外的程序(平台)使用導致另外的繪的一樣。
都可以在窗口上面繪圖
1.QPixmap繪圖設備
//繪圖設備, 400*300
QPixmap pixmap(400, 300);
QPainter p(&pixmap);
//填充白色背景色
//p.fillRect(0, 0, 400, 300, QBrush(Qt::white));
pixmap.fill(Qt::white);
p.drawPixmap(0, 0, 80, 80, QPixmap("../Image/face.png"));
//把繪圖設備中的圖片(繪畫結果)保存出來,保存圖片
pixmap.save("../pixmap.jpg");
2.QImage繪圖設備
//創建一個繪圖設備,QImage::Format_ARGB32背景是透明
QImage image(400, 300, QImage::Format_ARGB32);
QPainter p;
p.begin(&image);
//繪圖
p.drawImage(0, 0, QImage("../Image/face.png"));
//對繪圖設備前50個像素點進行操作
for(int i = 0; i < 50; i++)
{
for(int j = 0; j < 50; j++)
{
image.setPixel(QPoint(i, j), qRgb(0, 255, 0));
//image.pixel(QPoint(i, j));
}
}
p.end();
image.save("../image.png");
3.QPicture繪圖設備
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
QPicture picture;
QPainter p;
p.begin(&picture);
p.drawPixmap(0, 0, 80, 80, QPixmap("../Image/face.png"));
p.drawLine(50, 50, 150, 50);
p.end();
//保存的是二進制文件
picture.save("../picture.png");//把繪圖狀態(繪圖操作)保存為二進制文件
}
void Widget::paintEvent(QPaintEvent *)
{
QPicture pic;
//加載文件
pic.load("../picture.png"); //加載之前繪圖的操作,用於生成圖片
QPainter p(this);
p.drawPicture(0, 0, pic);
}
4.QImage和QPixmap相互轉換
QPixmap使用底層平台的繪制系統進行繪制,無法提供像素級別的操作,而QImage則是使用獨立於硬件的繪制系統,實際上是自己繪制自己,
因此提供了像素級別的操作,並且能夠在不同系統之上提供一個一致的顯示形式。
比如網絡傳輸的是QImage(因為和和平台無關),但是畫的時候需要有優化的QPixmap,這時就需要吧接收到的
QImage轉換為QPixmap
void Widget::paintEvent(QPaintEvent *)
{
QPainter p(this);
QPixmap pixmap;
pixmap.load("../Image/face.png");
//QPixmap -> QImage
QImage tempImage = pixmap.toImage();
p.drawImage(0, 0, tempImage);
QImage image;
image.load("../Image/face.png");
//QImage -> QPixmap
QPixmap tempPixmap = QPixmap::fromImage(image);
p.drawPixmap(100, 0, tempPixmap);
}
/*******************************************************************************************/
五、不規則窗口
常見的窗體是各種方形的對話框,但有時候也需要非方形的窗體,如圓形,橢圓甚至是不規則形狀的對話框。
實現步驟:
1.新建一個項目,比如項目名稱叫做“ShapeWidget”,給此項目添加一個類“ShapeWidget”,基類選擇“QWidget”。
2.為了使該不規則窗體可以通過鼠標隨意拖拽,在類中重定義鼠標事件:mousePressEvent()、mouseMoveEvent()、以及繪制函數paintEvent()
3.“ShapeWidget”的構造函數部分是實現該不規則窗體的關鍵,添加具體代碼如下:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//去窗口邊框
setWindowFlags(Qt::FramelessWindowHint | windowFlags());
//把窗口背景設置為透明,通過透明已經將窗口設置為圖片的樣式了,窗口和透明圖片一樣,當然就是不規則窗口了
setAttribute(Qt::WA_TranslucentBackground);
//注意,此時無法移動鼠標以及無法關閉整個特殊的窗口,所以需要重寫這些事件
//注意,移動窗口是行對於屏幕而言的,所以鼠標的坐標獲取是相對於窗口左上角而言的差值,移動也是移動到左上角。(移動的時候是以窗口的左上角移動的)
}
4.重新實現鼠標事件和繪制函數
void Widget::mousePressEvent(QMouseEvent *e)
{
if(e->button() == Qt::RightButton)
{
//如果是右鍵,關閉窗口
close();
}
else if(e->button() == Qt::LeftButton)
{
//求坐標差值
//坐標差值=當前點擊坐標-窗口左上角坐標 //之所以不用表示相對於窗口的坐標e->x/y,是因為這個e->x/y是相對於窗口的內邊框,而移動的是外邊框
p = e->globalPos() - this->frameGeometry().topLeft();//this->frameGeometry()獲取的是當前矩形窗口
//e->globalPos(),當前坐標 全局的,即相對於屏幕左上角的坐標。.topLeft()矩形窗口的左上角坐標
}
}
void Widget::mouseMoveEvent(QMouseEvent *e)
{
if(e->buttons() & Qt::LeftButton)
{
//把當前窗口中心點移動到左上角,即以當前的左上角作為移動后窗口的中心位置
move(e->globalPos() - p);//當前坐標(全局的)減去差值等於左上角坐標(全局的)
//參數里是移動到的位置
}
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter p(this);
p.drawPixmap(0, 0, QPixmap("../Image/sunny.png"));
}