zoukankan      html  css  js  c++  java
  • 界面编程之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"));

    }

  • 相关阅读:
    Hibernate 中 简便proxool连接池配置
    卸载oracle删除注册表脚本
    hibernate的@EmbeddedId嵌入式主键详解
    Activiti工作流学习(三)Activiti工作流与spring集成
    Activiti工作流学习(二)流程实例、执行对象、任务
    Activiti工作流学习(一)部署对象和流程定义
    Enum(枚举类型)的基本应用
    Activiti工作流引擎参考资料
    条形码参考资料
    推荐两款PC健康小软件
  • 原文地址:https://www.cnblogs.com/yuweifeng/p/9380766.html
Copyright © 2011-2022 走看看