界面编程之QT绘图和绘图设备20180728

/*******************************************************************************************/

一、绘图

整个绘图系统基于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
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 }
widget.cpp

/*******************************************************************************************/

三、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"));

}

posted @ 2018-07-28 09:44  yuweifeng  阅读(3918)  评论(0编辑  收藏  举报