QT 学习笔记(十一)

news2024/12/26 16:48:26

文章目录

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

在这里插入图片描述

  • 实现代码如下:
//绘图设备大小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 ,不是窗口。因此,我们可以直接在构造函数里面编写代码。

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

  • 实现代码如下:
    //创建一个绘图设备,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");

在这里插入图片描述

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

在这里插入图片描述

二、QPixmap 和 QBitmap 的区别

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

1. widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

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

3. 实现结果

在这里插入图片描述

  • 这里我们采用两张 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"));
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/111426.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python正在消亡?致命弱点是否会让Python被新语言取代?

被业界称为“瑞士军刀”的编程语言&#xff0c;可能会被更适合该任务的其他语言取代吗&#xff1f; 自从1990年代初Python发布以来&#xff0c;它引起了很多热议。当然&#xff0c;编程社区花了至少20年的时间才逐渐注意到它的存在&#xff0c;而当它一旦开始流行起来&#xf…

Web入门开发【一】- Web开发介绍

欢迎来到霍大侠的小院&#xff0c;我们来学习Web入门开发的系列课程。 首先我们来了解下这个课程能学到什么&#xff1f; 1、你将可以掌握Web网站的开发全过程。 2、了解基础的HTML&#xff0c;CSS&#xff0c;JavaScript语言。 3、开发自己的第一个网站。 4、认识很多对编…

UML类关系

1、聚合关系&#xff08;aggregation&#xff09; 用空心菱形箭头表示&#xff0c;整体和部分有各自的生命周期。部分可以属于多个整体对象! class Student; class Class { private: Student s; public: void set_student(Student s) { this.s s; } }; student() { print(“c…

电脑商城网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 作为一个网上商城系统&#xff0c;就应该做到能提供强大的业务支持功能&#xff0c;系统能实现用户的注册功能、登录 功…

整理各种Vue项目在IE浏览器白屏报错 SCRIPT1002:语法错误

目录 一、关于 sockjs-client 依赖包 二、关于 highlight 依赖包 三、关于 swiper 依赖包 四、IE 不支持 ES6 语法 五、第三方插件引入导致 六、本地环境正常&#xff0c;生产环境仍旧白屏 这篇文章主要介绍了 Vue 项目在 IE 浏览器显示白屏并报错 SCRIPT1002: 语法错误 …

【数字信号处理】卷积和乘法系列3之傅里叶变换对III

“傅里叶”家族 引言 虽然你知道傅里叶级数和变换,但看看它们之间的关系是很有趣的。本节的目的是展示各种基于傅立叶的变换如何相互关联。 要做到这一点,有必要认识到存在一个具有四个成员的傅里叶“家族”,如图 30 所示。有四个是因为除了具有系列与变换选项(行)外,…

转行的35岁程序员们

“大龄程序员去哪儿了”&#xff0c;10月24日程序员节当天&#xff0c;这成为了社交媒体上最火的话题之一。根据澎湃新闻统计&#xff0c;在知乎、豆瓣上关于“大龄程序员”的369个有效提问里&#xff0c;大龄程序员的职场成长问题最受关注&#xff0c;一共有242个&#xff0c;…

给刚入职场的年轻人八条建议

年轻人刚入职场时&#xff0c;总会碰到各种各样的难题&#xff0c;作为过来人&#xff0c;很多新人的难处我也深有体会。想要快速融入职场是没有捷径的&#xff0c;但是如果处理得当&#xff0c;还是可以少走很多弯路&#xff0c;以下就是我总结的给刚入职场的年轻人的八条建议…

JavaDS1-时间复杂度空间复杂度

目录 1.算法效率 1.1.时间效率&#xff08;时间复杂度&#xff09;——衡量算法运行速度 1.2.空间效率&#xff08;空间复杂度&#xff09;——衡量算法所需额外空间&#xff08;如今不再特别关注&#xff09; 2.时间复杂度 2.1.概念 2.2.大O的渐进表示法 2.2.1.O(F(n))…

【约数】魔法数

K-魔法数_2022河南萌新联赛第&#xff08;六&#xff09;场&#xff1a;郑州大学 (nowcoder.com) 题意&#xff1a; 思路&#xff1a; 一开始想的是枚举到1e6&#xff0c;统计所有数的约数个数&#xff0c;然后就不知道然后了&#xff0c;甚至想放到同一个数组里面然后lower_…

遇事不决,转行做程序员?先看看转了的人怎么说

遇事不决先“转码”——近几年&#xff0c;这好像成了非程序员考虑转行方向的优先选择。 转码&#xff0c;指放弃原职业或专业&#xff0c;转行成为程序员。通过“转码”这一跳板&#xff0c;有人在互联网行业谋得一份薪水更高的工作&#xff0c;还有人借此申请出国读书工作、…

大龄转行当程序员怎么做?应该选择小众技术,避免与年轻人竞争?

最近&#xff0c;一篇关于一位大龄人士转行&#xff0c;成为程序员的文章引起了关于 HN 的热议。文章作者 Derek M. Jones 是一名从事该行业十多年的软件工程师。最近&#xff0c;他遇到了许多想要转行到软件开发方面的年长求职者。对此&#xff0c;他的建议是&#xff1a;选择…

【源码共读】yocto-queue 一个微型队列数据结构

yocto-queue是一个微型队列的数据结构&#xff0c;根据作者的介绍&#xff0c;如果在你一个数据量很大的数组上&#xff0c;大量的操作Array.push和Array.shift&#xff0c;那么你可以考虑使用yocto-queue来替代Array。 因为Array.shift的时间复杂度是O(n)&#xff0c;而Queue…

长除法计算平方根的方法总结与代码实现(C++, Python)

tags: DSA Math C Python 写在前面 之前总结了计算平方根的方法, 但是并没有给出手算方法的解释, 这次专门写一下手算方法. 据说这个方法是中国的数学家创造的, 我也没深入考证过, 总之就是非常经典了, 因为这个长除法算法(英文:Long Division Algorithm)可以计算任意精度的…

《ESP32》Adafruit_GFX、u8g2驱动ssd1306

本示例将使用ESP32驱动ssd1306&#xff0c;将为你介绍SSD1306&#xff0c;接线方式以及如何使用Adafruit_GFX、u8g2两种模式进行开发SSD1306。 本人踩坑了半天&#xff0c;发现Adafruit_SSD1306并不能驱动器LVGL&#xff0c;其并没有实现关键的setAddrWindow和pushColors函数用…

【网络编程】第四章 网络套接字(守护进程+TCP英译汉+TCP通协议讯流程+TCP和UDP对比)

&#x1f3c6;个人主页&#xff1a;企鹅不叫的博客 ​ &#x1f308;专栏 C语言初阶和进阶C项目Leetcode刷题初阶数据结构与算法C初阶和进阶《深入理解计算机操作系统》《高质量C/C编程》Linux ⭐️ 博主码云gitee链接&#xff1a;代码仓库地址 ⚡若有帮助可以【关注点赞收藏】…

[Java]注解

文章目录⚽ 注解的概述⚽ 常见注解的使用示例&#x1f3d0; 文档相关的注解&#x1f3d0; 在编译时进行格式检查(JDK内置的三个基本注解)&#x1f3d0; 跟踪代码依赖性&#xff0c;实现替代配置文件功能⚽ 自定义注解⚽ JDK中的元注解&#x1f3d0; Retention&#x1f3d0; Tar…

【PowerDesign】制作数据流图

目录 文章目录 前言 一、下载软件 二、使用步骤 1.打开面板 2.绘制顶层0层/数据流程图 创建加工 画出数据流向 对格式进行设置 结果展示 2. 1层数据流程图 生成子加工 框图格式设置 结果展示 注意事项 3. 2层数据流程图 总结 前言 本文以图书管理系统举例&…

java开发的环保网站垃圾分类系统源码

本项目是基于springboot开发的小区垃圾分类的监管系统。为了更好的督促小区业主更好的进行垃圾分类和垃圾投放&#xff0c;本系统设计了一套积分奖罚机制&#xff0c;如果业主此次投放垃圾符合分类要求则加10积分&#xff0c;不符合则扣除200积分&#xff0c;积分不够需要进行扫…

东北大学c++实验最后一次

【问题描述】 建立两个磁盘文件f1.txt和f2.txt&#xff0c;编写程序实现以下工作&#xff1a; &#xff08;1&#xff09;从文件in.txt输入20个整数&#xff0c;分别存放在两个磁盘文件f1.txt和f2.txt中&#xff08;每个文件中放10个整数&#xff09;&#xff1b; &#xff…