QT 学习笔记(十一)

文章目录

  • 一、绘图设备
    • 1. QPixmap
      • 1.1 QPixmap 简介
      • 1.2 QPixmap 演示
    • 2. QBitmap
      • 2.1 QBitmap 简介
      • 2.2 QBitmap 演示见 QPixmap 和 QBitmap 的区别。
    • 3. QImage
      • 3.1 QImage 简介
      • 3.2 QImage 演示
    • 4. QPicture
      • 4.1 QPicture 简介
      • 4.2 QPicture 演示
  • 二、QPixmap 和 QBitmap 的区别
    • 1. widget.h
    • 2. widget.cpp
    • 3. 实现结果
  • 三、QPixmap 与 QImage 的区别和相互转换
    • 1. QImage 与 QPixmap 的区别
    • 2. QImage 与 QPixmap 的相互转换
  • 四、不规则窗口

由于每次代码都是在原有程序上修改,因此除了新建项目,不然一般会在学完后统一展示代码。
提示:具体项目创建流程和注意事项见QT 学习笔记(一)
提示:具体项目准备工作和细节讲解见QT 学习笔记(二)

一、绘图设备

  • 绘图设备是指继承 QPainterDevice 的子类。 QT 一共提供了四个这样的类,分别是 QPixmap、QBitmap、QImage 和 QPicture。
  • QPixmap 专门为图像在屏幕上的显示做了优化,和平台相关,不能对图片进行修改。
  • QBitmap 是 QPixmap 的一个子类,它的色深限定为 1,可以使用 QPixmap 的 isQBitmap() 函数来确定这个 QPixmap 是不是一个 QBitmap。
  • QImage 专门为图像的像素级访问做了优化。,和平台无关,可以对图片进行修改, 在线程中绘图。
  • QPicture 可以记录和重现 QPainter 的各条命令,保存绘图的状态(二进制文件)。

1. QPixmap

  • 生成一个新的项目,具体步骤过程见提示。

1.1 QPixmap 简介

  • (1) QPixmap 继承了 QPaintDevice 。因此,可以使用 QPainter 直接在上面绘制图形。
  • (2) QPixmap 可以接受一个字符串作为一个文件的路径来显示这个文件,比如想在程序之中打开 png、jpeg 之类的文件,就可以使用 QPixmap。
  • (3) 使用 QPainter 的 drawPixmap() 函数可以把这个文件绘制到一个 QLabel、QPushButton 或者其他的设备上面。
  • (4) QPixmap 是针对屏幕进行特殊优化的。因此,它与实际的底层显示设备息息相关。注意,这里说的显示设备并不是硬件,而是操作系统提供的原生的绘图引擎。所以,在不同的操作系统平台下,QPixmap 的显示可能会有所差别。

1.2 QPixmap 演示

  • 我们现在指定绘图设备 QPixmap,不是窗口。因此,我们可以直接在构造函数里面编写代码。

QT 学习笔记(十一)_第1张图片

  • 运行后,在 QT 的运行结果上并没有现象。但是,在我们的文件当中,会生成一个 QPixmap.png 的图片文件。打开后,我们发现图片的背景颜色是黑色。
  • 在应用的时候,我们往往按照需求对背景色进行填充。在这里以背景色为白色举例。

QT 学习笔记(十一)_第2张图片

  • 实现代码如下:
//绘图设备大小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("../tuoian/5.jpg"));

    //保存图片
    pixmap.save("../pixmap.png");

2. QBitmap

2.1 QBitmap 简介

  • (1) QBitmap 继承于 QPixmap,因此具有 QPixmap 的所有特性,提供单色图像。
  • (2) QBitmap 的色深始终为1,色深这个概念来自计算机图形学,是指用于表现颜色的二进制的位数。计算机里面的数据都是使用二进制表示的。为了表示一种颜色,我们也会使用二进制。比如我们要表示 8 种颜色,需要用 3 个二进制位,这时我们就说色深是 3。因此,所谓色深为 1,也就是使用 1 个二进制位表示颜色。1 个位只有两种状态:0 和 1,因此它所表示的颜色就有两种,黑和白。因此,QBitmap 实际上是只有黑白两色的图像数据。
  • (3) 由于 QBitmap 色深小,因此只占用很少的存储空间,所以适合做光标文件和笔刷。

2.2 QBitmap 演示见 QPixmap 和 QBitmap 的区别。

3. QImage

  • 生成一个新的项目,具体步骤过程见提示。

3.1 QImage 简介

  • (1) QImage 是使用独立于硬件的绘制系统,实际上是自己绘制自己,因此提供了像素级别的操作,并且能够在不同系统之上提供一个一致的显示形式。
  • (2) 我们声明了一个 QImage 对象,大小是 300 x 300,颜色模式是 RGB32,即使用 32 位数值表示一个颜色的 RGB 值,也就是说每种颜色使用 8 位。然后我们对每个像素进行颜色赋值,从而构成了这个图像。我们可以把 QImage 想象成一个 RGB 颜色的二维数组,记录了每一像素的颜色。

3.2 QImage 演示

  • 我们现在指定绘图设备 QImage ,不是窗口。因此,我们可以直接在构造函数里面编写代码。

QT 学习笔记(十一)_第3张图片

  • ARGB 应用背景是透明色,RGB 的背景是黑色。在这里我们选用 QImage::Format_ARGB32 背景是透明,现象如下图所示:

QT 学习笔记(十一)_第4张图片

  • QImage 可以对像素点进行操作,现象如下图所示:

QT 学习笔记(十一)_第5张图片

  • 实现代码如下:
    //创建一个绘图设备,QImage::Format_ARGB32 背景是透明
    QImage image(400,300,QImage::Format_ARGB32);
    QPainter p;
    p.begin(&image);

    //绘图
    p.drawImage(0,0,QImage("../tuoian/5.jpg"));

    //对绘图设备前50个像素点进行操作
    for(int i=0;i<50;i++)
    {
        for(int j=0;j<50;j++)
        {
            image.setPixel(QPoint(i, j), qRgb(0,255,0));
        }
    }

    p.end();

    //保存图片
    image.save("../image.png");

4. QPicture

  • 生成一个新的项目,具体步骤过程见提示。

4.1 QPicture 简介

  • (1) QPicture 是一个可以记录和重现 QPainter 命令的绘图设备。
  • (2) QPicture 将 QPainter 的命令序列化到一个 I/O 设备,保存为一个平台独立的文件格式。这种格式有时候会是“元文件(meta- files)”。QT 的这种格式是二进制的,不同于某些本地的元文件,QT 的 pictures 文件没有内容上的限制,只要是能够被 QPainter 绘制的元素,不论是字体还是 pixmap,或者是变换,都可以保存进一个 picture 中。
  • (3) QPicture 是平台无关的,因此它可以使用在多种设备之上,比如 svg、pdf、ps、打印机或者屏幕。这里所说的 QPaintDevice,实际上是说可以有 QPainter 绘制的对象。QPicture 使用系统的分辨率,并且可以调整 QPainter 来消除不同设备之间的显示差异。
  • (4) 如果要记录下 QPainter 的命令,首先要使用 QPainter::begin() 函数,将 QPicture 实例作为参数传递进去,以便告诉系统开始记录,记录完毕后使用 QPainter::end() 命令终止。

4.2 QPicture 演示

  • 我们现在指定绘图设备 QPicture ,不是窗口。因此,我们可以直接在构造函数里面编写代码。
  • QPicture 文件生成的图片是二进制文件,在文件路径下图片是无法打开的,实现代码和现象如下图所示:
    QPicture picture;
    QPainter p;
    p.begin(&picture);

    //绘图
    p.drawPixmap(0,0,80,80,QPixmap("../tuoian/5.jpg"));
    p.drawLine(50,50,150,50);

    p.end();

    //保存的是二进制文件
    picture.save("../picture.png");

QT 学习笔记(十一)_第6张图片

  • 如果我们想观察到生成的图片,需要在头文件 widget.h 当中的 protected 下进行 paintEvent 的声明,在源文件 widget.cpp 下进行实现,实现代码和现象如下图所示:
void Widget::paintEvent(QPaintEvent *)
{
    QPicture pic;
    pic.load("../picture.png");
    
    QPainter p(this);
    p.drawPicture(0,0,pic);
}

QT 学习笔记(十一)_第7张图片

二、QPixmap 和 QBitmap 的区别

  • 生成一个新的项目,具体步骤过程见提示。
  • QPixmap 主要是画彩色;QBitmap 只有黑白两种颜色。
  • 下面进行同一个图像文件在 QPixmap 和 QBitmap 下的不同表现,以便于我们可以更直观的观察到区别。

1. widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include 

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
    
protected:
    //重写绘图事件
    //如果给窗口绘图,一定要在paintEvent()中实现
    void paintEvent(QPaintEvent *);

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

2. widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include 
#include 

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);
}

3. 实现结果

QT 学习笔记(十一)_第8张图片

  • 这里我们采用两张 png 图片。butterfly1.png 是没有透明色的纯白背景,而 butterfly.png 是具有透明色的背景。我们分别使用 QPixmap 和 QBitmap 来加载它们。
  • 可以很明显知道它们的区别:白色的背景在 QBitmap 中消失了,而透明色在 QBitmap 中转换成了黑色;其他颜色则是使用点的疏密程度来体现的。

三、QPixmap 与 QImage 的区别和相互转换

1. QImage 与 QPixmap 的区别

  • (1) QPixmap 主要是用于绘图,针对屏幕显示而最佳化设计;QImage 主要是为图像 I/O、图片访问和像素修改而设计的。
  • (2) QPixmap 依赖于所在的平台的绘图引擎,故例如反锯齿等一些效果在不同的平台上可能会有不同的显示效果;QImage 使用 QT 自身的绘图引擎,可在不同平台上具有相同的显示效果。
  • (3) QImage 是独立于硬件的,也是一种 QPaintDevice,因此我们可以在另一个线程中对其进行绘制,而不需要在 GUI 线程中处理,使用这一方式可以很大幅度提高 UI 响应速度。
  • (4) QImage 可通过 setPixpel() 和 pixel() 等方法直接存取指定的像素。

2. QImage 与 QPixmap 的相互转换

  • (1) QImage 转换为 QPixmap
  • 使用 QPixmap 的静态成员函数 fromImage()。
QPixmap	tempPixmap = QPixmap::fromImage(image);
  • (2) QPixmap 转换为 QImage :
  • 使用 QPixmap 类的成员函数 toImage()。
QImage tempImage = pixmap.toImage();

四、不规则窗口

  • 生成一个新的项目,具体步骤过程见提示。
  • 常见的窗体是各种方形的对话框,但有时候也需要非方形的窗体,如圆形,椭圆甚至是不规则形状的对话框。
  • 不规则窗口的实现步骤:
  • (1) 新建一个项目,比如项目名称叫做 ShapeWidget,给此项目添加一个类 ShapeWidget,基类选择 QWidget。
  • (2) 为了使该不规则窗体可以通过鼠标随意拖拽,在类中重定义鼠标事件:mousePressEvent()、mouseMoveEvent()、以及绘制函数 paintEvent()。
  • (3) ShapeWidget 的构造函数部分是实现该不规则窗体的关键,具体代码如下:
    //新建一个Pixmap对象
    QPixmap pixmap;
    //加载图片
    pixmap.load("../tuoian/7.jpg");
   //固定窗口大小,将窗口大小设置为图片大小
    setFixedSize( pixmap.width(), pixmap.height() );
    //给窗口去掉边框,设置窗口的flags
    setWindowFlags(Qt::FramelessWindowHint | windowFlags() );
    //设置透明背景
    setAttribute(Qt::WA_TranslucentBackground);
  • (4) 重新实现鼠标事件和绘制函数,具体代码如下:
void ShareWidget::mousePressEvent(QMouseEvent *ev)
{
    if(ev->button() == Qt::LeftButton)
    {
        //求坐标插值
        //当前点击坐标-窗口左上角坐标
        m_dragPoint = ev->globalPos()-frameGeometry().topLeft();
    }
    else if(ev->button() == Qt::RightButton)
    {
        // 鼠标右键关闭窗口
        close();
    }
}

void ShareWidget::mouseMoveEvent(QMouseEvent *ev)
{
    if(ev->buttons() & Qt::LeftButton)
    {
        // 如果是鼠标左键拖动, 移动窗口
        move(ev->globalPos() - m_dragPoint);
    }
}

void ShareWidget::paintEvent(QPaintEvent *ev)
{
    Q_UNUSED(ev)
    QPainter painter(this);
    // 重新绘制图片
    painter.drawPixmap(0, 0, QPixmap(":/ButterFly"));
}

你可能感兴趣的:(QT,qt,学习,开发语言)