C++客户端Qt开发——界面优化(绘图)

news2024/9/22 9:50:41

2.绘图

Qt提供了画图相关的APL,可以允许我们在窗口上绘制任意的图形形状,来完成更复杂的界面设计

所谓的"控件",本质上也是通过画图的方式画上去的

画图AP|和控件之间的关系,可以类比成机器指令和高级语言之间的关系

控件是对画图API的进一步封装;画图API是控件的底层实现

说明

QPainter

"绘画者"或者"画家"

用来绘图的对象,提供了一系列drawXXX方法,可以允许我们绘制各种图形

QPaintDevice

"画板”

描述了QPainter把图形画到哪个对象上.像咱们之前用过的QWidget也是一种QPaintDevice(QWidgetQPaintDevice的子类)

QPen

"画笔"

描述了QPainter画出来的线是什么样的

QBrush

"画刷"

描述了QPainter填充一个区域是什么样的.

绘图API的使用,一般不会在QWidget的构造函数中使用,而是要放到paintEvent事件中

关于paintEvent

paintEvent会在以下情况下被触发:

  • 控件首次创建
  • 控件被遮挡,再解除遮挡
  • 窗口最小化,再恢复
  • 控件大小发生变化时
  • 主动调用repaint()或者update()方法。(这两个方法都是QWidget的方法)

因此,如果把绘图 API 放到构造函数中调用,那么一旦出现上述的情况,界面的绘制效果就无法确保符合预期了

①绘制各种形状

1>绘制线段

 

078eb3b06bc2380568b82ecba3581d0f.png

 

0e3ddd792bb6e147f75ac3845da7ebd7.png

①:void drawLine(const QPoint &p1,const QPoint &p2); p1:绘制起点坐标;p2:绘制终点坐标

②:void QPainter:drawRect(int x,int y,int width,int height); x:窗口横坐标;y:窗口纵坐标;width:所绘制矩形的宽度;height:所绘制矩形的高度;

2>绘制矩形

 

bddce80bf464dd5d17ed3a600adc5895.png

void QPainter:drawRect(int x,int y,int width,int height); ×:窗口横坐标;y:窗口纵坐标;width:所绘制矩形的宽度;height:所绘制矩形的高度;

3>绘制圆形

 

df6ea151bf079d60baae622f85c2cb4e.png

void QPainter:drawEllipse(const QPoint &center,int rx,int ry); center:中心点坐标; r×:横坐标; ry:纵坐标

4>绘制文本

 

e69f0d2db878d5e2dad54ab03aa05260.png

#include "widget.h"
#include "ui_widget.h"
#include<QPainter>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::paintEvent(QPaintEvent *)
{
    //实例化画家对象,this表示的是在当前窗口中绘画,即绘图设备
    QPainter painter(this);

    //画一条线
    painter.drawLine(QPoint(20,20),QPoint(200,20));

    //再画一条线
    painter.drawLine(20,100,200,100);

    //绘制矩形
    painter.drawRect(120,120,100,50);

    //绘制圆
    painter.drawEllipse(QPoint(400,200),50,50);



    //绘制文本
    QFont font("华文行楷",24);
    painter.setFont(font);

    //设置画笔颜色
    painter.setPen(Qt::blue);

    //画文字
    painter.drawText(QRect(100,200,600,150),"Outlier9");
    //坐标如果写成(0,0),就不会显示出来,因为在基线的位置之上
    //所以一般y设置为100,基线的位置一般大概在文字的三分之二处
}

5>设置画笔

QPainter在绘制时,是有一个默认的画笔的。在使用时也可以自定义画笔。在Qt中,QPen类中定义了QPainter应该如何绘制形状、线条和轮廓。同时通过QPen类可以设置画笔的线宽、颜色、样式、画刷等。

画笔的颜色可以在实例化画笔对象时进行设置

画笔的宽度是通过setWidth()方法进行设置

画笔的风格是通过setStyle()方法进行设置

设置画刷主要是通过setBrush()方法

  • 设置画笔颜色:QPen:QPen(const QColor &color) 画笔的颜色主要是通过QColor类设置;
  • 设置画笔宽度:void QPen:setWidth(int width)
  • 设置画笔风格:void QPen:setStyle(Qt:PenStyle style)

画笔风格展示:

 

9bb66c4b77a9a2477682c2068f54e588.png

画笔使用

 

1c1e133003b8af4a306b4d2b49d7b632.png

#include "widget.h"
#include "ui_widget.h"
#include<QPainter>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::paintEvent(QPaintEvent *)
{
    //实例化画家对象,this表示的是在当前窗口中绘画,即绘图设备
    QPainter painter(this);


    //设置画笔
    QPen pen(QColor(255,0,0));
    //设置画笔宽度
    pen.setWidth(3);
    //设置画笔风格
    pen.setStyle(Qt::DashLine);
    //设置让画家使用画笔
    painter.setPen(pen);


    //画一条线
    painter.drawLine(QPoint(20,20),QPoint(200,20));

    //再画一条线
    painter.drawLine(20,100,200,100);

    //绘制矩形
    painter.drawRect(120,120,100,50);

    //绘制圆
    painter.drawEllipse(QPoint(400,200),50,50);



    //绘制文本
    QFont font("华文行楷",24);
    painter.setFont(font);

    //设置画笔颜色
    painter.setPen(Qt::blue);

    //画文字
    painter.drawText(QRect(100,200,600,150),"Outlier9");
}

6>设置画刷

在Qt中,画刷是使用QBrush类来描述,画刷大多用于填充。QBrush定义了QPainter的填充模式,具有样式、颜色、渐变以及纹理等属性。

画刷的格式中定义了填充的样式,使用Qt:BrushStyle枚举,默认值是Qt:NoBrush,也就是不进行任何填充。可以通过Qt助手查找画刷的格式。如下图示:

 

14195f9db38026f4545bb1fdafc7fd8e.png

 

720c8cdbbb70447ca3d850afe742c397.png

 

0c0e2ad948d760c3584be31b404b4e25.png

 

53c9cf9a9dfbb2d2a17bb188d5477588.png

设置画刷主要通过void QPen:setBrush(const QBrush &brush)方法,其参数为画刷的格式。

 

fda9e6b21086acee8255439bae57ef5b.png

#include "widget.h"
#include "ui_widget.h"
#include<QPainter>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::paintEvent(QPaintEvent *)
{
    //实例化画家对象,this表示的是在当前窗口中绘画,即绘图设备
    QPainter painter(this);


    //设置画笔
    QPen pen(QColor(255,0,0));
    //设置画笔宽度
    pen.setWidth(3);
    //设置画笔风格
    pen.setStyle(Qt::DashLine);
    //设置让画家使用画笔
    painter.setPen(pen);


    //设置画刷,给封闭图形填充颜色
    QBrush brush(Qt::cyan);
    //设置画刷风格
    brush.setStyle(Qt::Dense1Pattern);
    //让画家使用画刷
    painter.setBrush(brush);



    //画一条线
    painter.drawLine(QPoint(20,20),QPoint(200,20));

    //再画一条线
    painter.drawLine(20,100,200,100);

    //绘制矩形
    painter.drawRect(120,120,100,50);

    //绘制圆
    painter.drawEllipse(QPoint(400,200),50,50);



    //绘制文本
    QFont font("华文行楷",24);
    painter.setFont(font);

    //设置画笔颜色
    painter.setPen(Qt::blue);

    //画文字
    painter.drawText(QRect(100,200,600,150),"Outlier9");
}

②绘制图片

Qt提供了四个类来处理图像数据:QImageQPixmapQBitmapQPicture,它们都是常用的绘图设备。其中QImage主要用来进行I/O处理,它对I/O处理操作进行了优化,而且可以用来直接访问和操作像素;QPixmap主要用来在屏幕上显示图像,它对在屏幕上显示图像进行了优化;QBitmapQPixmap的子类,用来处理颜色深度为l的图像,即只能显示黑白两种颜色;QPicture用来记录并重演QPainter命令。这里只讲解QPixmap

 

c4779aa7a2101cd7bc74d6a3c40b7c66.png

添加资源文件时,先将准备好的照片都放到一个文件夹内,文件夹与项目文件同级

 

696d6ccbcad40ca99cbc8e59256242be.png

添加的时候,选中项目文件然后右键add New

 

7452d826f073d6c68c363ed54e84ab30.png

然后把图片都添加进去

 

a756d197231c9d87fde0c263577b11a7.png

点击构建并运行,加载资源图片到项目中

图片的平移、放大缩小、旋转

  • QPainter类中提供了translate()函数来实现坐标原点的改变
  • 图片的放大和缩小可以使用QPainter类中的drawPixmap()函数来实现。
  • 图片的旋转使用的是QPainter类中的rotate()函数,它默认是以原点为中心进行旋转的。如果要改变旋转的中心,可以使用translate()函数完成。

 

069cf57efaabb730102eeb61f78cefdd.png

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    //声明绘画事件
    void paintEvent(QPaintEvent *event);

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

在绘制图形的过程中,可以通过save()函数来保存画家的状态,使用restore()函数还原画家状态。

save()函数原型

 

99cb039d173c5366fc1640034f6307a5.png

restore()函数原型

 

afe02e78c14ed674bc4cec145845fac5.png

③特殊的绘图设备

  • QPixmap用于在显示器上显示图片
  • QImage用于对图片进行像素级修改
  • QPicture用于对QPainter的一系列操作进行存档

1>QPixmap

QPixmap核心特性:

  • 使用QPainter直接在上面进行绘制图形.
  • 通过文件路径加载并显示图片,
  • 搭配QPainterdrawPixmap()函数,可以把这个图片绘制到一个QLabelQPushButton等控件上
  • 和系统/显示设备强相关,不同系统/显示设备下,QPixmap的显示可能会有所差别

 

9c7f58daa99a9aed46cac2fab323feb2.png

#include "widget.h"
#include "ui_widget.h"
#include<QPixmap>
#include<QPainter>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //Pixmap绘图设备,绘图设备尺寸为500*500
    QPixmap pix(500,500);
    //实例化画家对象
    QPainter painter(&pix);
    //设置画笔颜色
    painter.setPen(Qt::red);
    //画图
    painter.drawEllipse(QPoint(100,100),100,100);
    //保存绘制的图片
    pix.save("D:\\C C++\\program\\QT\\QPainter\\picture\\pix.png");
}

Widget::~Widget()
{
    delete ui;
}

2>QImage

QImage的核心特性:

  • 使用OPainter直接在上面进行绘制图形
  • 通过文件路径加载并显示图片
  • 能够针对图片进行像素级别的操作(操作某个指定的像素).
  • 独立于硬件的绘制系统,能够在不同系统之上提供一致的显示

 

75965c4166e215c27845d0afb5b446bb.png

#include "widget.h"
#include "ui_widget.h"
#include<QPainter>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //绘图设备的大小为500*500,绘图格式为QImage::Format_RGB32
    //绘图格式可通过Qt助手查看
    QImage img(500,500,QImage::Format_RGB32);

    img.fill(Qt::white); // 填充色为白色,默认背景色为黑色

    QPainter painter(&img); //声明画家,画图设备为img

    painter.setPen(QPen(Qt::cyan));//设置画笔颜色为蓝绿色

    painter.drawEllipse(QPoint(200,200),100,100); //画圆
    //保存图片
    img.save("D:\\C C++\\program\\QT\\QImage\\img.jpg");

}

Widget::~Widget()
{
    delete ui;
}

QImage对像素的修改

 

f252eb6b6fd4b90fadcced6bb9bd0ed2.png

#include "widget.h"
#include "ui_widget.h"
#include<QPainter>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::paintEvent(QPaintEvent *)
{
    //实例化
    QPainter painter(this);
    QImage img;
    img.load(":/picture/3.png");

    //修改像素点
    for (int i = 100;i < 200; i++) {
        for (int j = 100;j < 200; j++) {
            QRgb rgb = qRgb(0,0,255);
            img.setPixel(i,j,rgb);
        }
    }

    painter.drawImage(0,0,img);
}

3>QPicture

OPicture核心特性:

  • 使用QPainter直接在上面进行绘制图形
  • 通过文件路径加载并显示图片.
  • 能够记录QPainter的操作步骤,
  • 独立于硬件的绘制系统,能够在不同系统之上提供一致的显示

注意:

QPicture加载的必须是自身的存档文件,而不能是任意的png,jpg等图片文件

QPicture类似于很多游戏的Replay功能

例如像war3这样的经典游戏,即使是一场60分钟的膀胱局,生成的replay文件,也不过几百个KB

此处的Replay功能并非是把整个游戏画面都录制保存下来,而是记录了地图中发生的所有事件(地图元素,玩家单位操作,中立生物行为等)

当回放Replay的时候其实就是把上述记录的事件再一条一条的执行一遍即可还原之前的游戏场景了

不了解游戏的同学,也可以理解成警察蜀黍录笔录,并通过笔录还原案发现场

如果要记录下QPainter的命令,首先要使用QPainter:begin()函数,将QPicture实例作为参数传递进去,以便告诉系统开始记录,记录完毕后使用QPainter:end()命令终止。如下示例:

 

d616210e26a9ac48b2d969fc9408f22a.png

#include "widget.h"
#include "ui_widget.h"
#include<QPicture>
#include<QPainter>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPicture pic;
    QPainter painter;
    painter.begin(&pic); // 开始往pic绘图设备上绘画
    painter.setPen(QPen(Qt::red)); // 设置画笔颜色为红色
    painter.drawEllipse(QPoint(200,200),100,100);
    painter.end();//结束绘画
    pic.save("D:\\C C++\\program\\QT\\QPicture\\picture\\pic.pic");
}

Widget::~Widget()
{
    delete ui;
}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

    //重现绘图指令
    QPicture pic;
    pic.load("D:\\C C++\\program\\QT\\QPicture\\picture\\pic.pic");
    painter.drawPicture(0,0,pic);
}

④界面优化

其他美化方式包括但不限于:

  • Qt动画
  • Qt3D图形
  • QQuick
  • 使用第三方控件库
  • Qt Design Studio

这里不做过多介绍了

 

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

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

相关文章

大模型“挣钱”新方法!用GPT-4优化众筹文稿,提高筹款成功率11.9%!

怎么才能在大模型时代&#xff0c;更好地通过大模型&#xff08;LLM&#xff09;来挣钱&#xff1f;写软文拿打赏&#xff0c;画海报给甲方&#xff0c;或者制作视频来打造个人IP&#xff1f;不够&#xff0c;还想要更直接一点的方式&#xff1f;那有没有一种可能&#xff0c;直…

密码学基础-为什么使用真随机数(True Random Number Generators)

密码学基础-为什么使用真随机数&#xff08;True Random Number Generators&#xff09; 概述 随机的意义很重要&#xff0c;就像你的银行密码如果是亲朋好友的生日&#xff0c;结婚纪念日&#xff08;可预测的&#xff09;&#xff0c;那么就容易被人测试出来&#xff1b;而…

Centos 7配置问题

在VMWare12上面安装Centos 7 Linux虚拟机&#xff0c;在切换到命令界面时&#xff0c;需要登录用户名和密码&#xff0c;但发现输入用户后有字符显示&#xff0c;但是密码没有。 经过一系列查看后&#xff0c;发现这个是Linux的一种机制&#xff0c;即当你输入密码时不显示&…

Python批量移除Word文档水印

Word文档被广泛用于各种正式与非正式的沟通场合。有时候这些文档中可能包含着不再需要的水印&#xff0c;比如早期的草稿标记、保密声明或是仅供预览的信息等。这些水印的存在可能会干扰文档的阅读体验&#xff0c;甚至在某些情况下导致信息传达的不准确或产生误解。移除Word文…

QT:多版本同时使用(5.15.2在线安装教程)

前言 根据不同项目的需要有时候不得不安装多个版本的QT&#xff0c;新版本的QT都需要在线安装&#xff0c;以下为QT5.15.2的在线安装办法&#xff08;5.15.2为LTS版本相对更稳定&#xff09;&#xff0c;老版本可参考之前的离线安装&#xff0c; 版本选择 比如 5.15.2 是完整的…

昇思25天学习打卡营第XX天|Diffusion扩散模型

扩散模型自DDPM论文提出后&#xff0c;在图像生成领域取得了显著进展&#xff0c;特别是在文本条件图像生成方面。重要发展包括改进的去噪模型&#xff0c;级联扩散模型以提高图像分辨率&#xff0c;以及无需分类器的扩散模型指导。DALL-E 2和ImageGen等模型展示了结合语言模型…

7.29 Day11 LVM逻辑卷管理

LVM逻辑卷管理&#xff1a; 优点&#xff1a;将多个磁盘进行统一管理&#xff0c;易于扩容 缺点&#xff1a;不支持容错&#xff08;任意一个磁盘坏了&#xff0c;整个磁盘都会坏&#xff09; 实现步骤&#xff1a; 对磁盘进行分区--改为8e--PV&#xff08;物理卷&#xff0…

pythonGame-实现羊了个羊简易字母版

通过python简单复现羊了个羊游戏。 使用到的库函数&#xff1a; import pygame import random 游戏源码&#xff1a; import pygame import random# 初始化pygame pygame.init()# 设置窗口大小 WIDTH 800 HEIGHT 600 screen pygame.display.set_mode((WIDTH, HEIGHT)) p…

基于N32L406MB EasyFlash参数(key-value)记录库移植

EasyFlash 感谢作者的分享https://github.com/armink/EasyFlash EasyFlash是一款开源的轻量级嵌入式Flash存储器库&#xff0c;方便开发者更加轻松的实现基于Flash存储器的常见应用开发 三大实用功能 ENV快速保存产品参数(key-value)&#xff0c;支持 写平衡&#xff08;磨…

文心智能体零代码开发实践,创建一个智能体:从理论到实践AI技术落地

文心智能体引领零代码智能体开发新风尚&#xff0c;诚邀您一同探索这前沿科技的魅力&#xff01;以下为实践创建一个叫”从理论到实践AI技术落地“智能体的步骤。 首先登录官网&#xff1a;文心智能体平台AgentBuilder | 想象即现实 登录后点击&#xff1a;创建智能体 输入“…

《660》+《880》强化带刷计划‼️45天吃透所有核心知识点

如果把660吃透再去做880&#xff0c;肯定会轻松一些&#xff01; 因为660题对于基础的考查很深入&#xff0c;每一道题都有难度&#xff0c;都需要认真思考才能做出来&#xff0c;所以&#xff0c;660建议在基础结束之后再开始做&#xff0c;因为基础阶段本身对基础知识的理解…

240731-一图解释LM-Studio如何设置模型的国内下载

感谢微信公众号作者数翼分享的文章 — 本地 LLM 可视化工具 LM Studio 突破国内网络限制使用 A. 图文指南 B. 具体步骤 Step 1. 安装软件并通过VSCode等编辑打开软件所在目录 官网下载并安装。随后找到软件的安装路径&#xff0c;并通过VSCode打开。 Step 2. 全局替换 被替…

2024年8月1日 十二生肖 今日运势

小运播报&#xff1a;2024年8月1日&#xff0c;星期四&#xff0c;农历六月廿七 &#xff08;甲辰年辛未月丁酉日&#xff09;&#xff0c;法定工作日。今天建军节&#xff0c;祝保家卫国、英勇无畏的解放军战士们节日快乐&#xff01; 红榜生肖&#xff1a;龙、牛、猪 需要注…

JavaSE基础 (认识String类)

一&#xff0c;什么是String类 在C语言中已经涉及到字符串了&#xff0c;但是在C语言中要表示字符串只能使用字符数组或者字符指针&#xff0c;可以使用标准库提 供的字符串系列函数完成大部分操作&#xff0c;但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想&…

vue中scoped详解以及样式穿透>>>、/deep/、::v-deep

1、scoped scoped属性用于限制样式仅应用于当前组件。当一个style标签拥有scoped属性时&#xff0c;它的CSS样式就只能作用于当前的组件&#xff0c;通过该属性&#xff0c;可以使得组件之间的样式不互相污染。 原理&#xff1a;当样式中加了scoped属性时候&#xff0c;编译的…

解决 Python 中 AttributeError: module ‘typing‘ has no attribute ‘_ClassVar‘

启动 Flask 的时候遇到&#xff1a; AttributeError: module typing has no attribute _ClassVar 卸载 dataclasses pip uninstall dataclasses 启动 Flask 正常

jenkins pipeline 发布 jar并运行

废话不多说&#xff0c;上教程 一&#xff0c;配置publish ssh 二&#xff0c;配置 ssh server 记住Name 三 设置发布选项 1 设置模块多选&#xff08;请安装多选插件&#xff1a;Active Choices Plug-in&#xff09; ​ ​ 四 编写pipeline 说明&#xff1a; 1 module…

vue项目实战 vueCropper 仿微信头像任意区域截取图片,上传到腾讯云保存

在package.json中添加 "vue-cropperjs": "4", 后在控制台执行&#xff1a;npm install ImageCropper.vue <template><div v-if"src"><!-- Vue Cropper区域 --><el-row class"cropper-wrapper" v-if"src…

stm32_按键消抖_代码与流程分析

stm32按键消抖 一 问题背景二 解决思路三 代码实现 一 问题背景 开关按钮&#xff1a;按下信号为0&#xff0c;正常信号为1 在按下时&#xff0c;表面上看我们只按了一下&#xff0c;但信号的传递并不是单纯的由1直接变为0。这是由于机械触点断开/闭合时会有抖动&#xff0c;…

北京大学:利用好不确定性,8B小模型也能超越GPT-4

大模型有一个显著的特点&#xff0c;那就是不确定性——对于特定输入&#xff0c;相同的LLM在不同解码配置下可能生成显著不同的输出。 比如问一问chatgpt“今天开心吗&#xff1f;”&#xff0c;可以得到两种不同的回答。 常用的解码策略有两种&#xff0c;一个是贪婪解码&am…