QT 学习笔记(十)

news2025/1/23 9:18:52

文章目录

  • 一、绘图
    • 1. 理论知识储备
    • 2. 画背景图
    • 3. 简单绘图
    • 4. 手动刷新窗口
  • 二、绘图实现代码
    • 1. 主窗口头文件 widget.h
    • 2. 主窗口头文件 widget.cpp

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

一、绘图

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

1. 理论知识储备

  • 使用 QT 画图的操作比较类似对文件进行操作,不会太难,控件较多。
  • QT 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制。
  • 整个绘图系统基于 QPainter,QPainterDevice 和 QPaintEngine 三个类。
  • QPainter 是用来执行绘制的操作;
  • QPaintDevice 是一个二维空间的抽象,这个二维空间允许QPainter在其上面进行绘制,也就是QPainter工作的空间;
  • QPaintEngine 提供了画笔(QPainter)在不同的设备上进行绘制的统一的接口。QPaintEngine 类应用于 QPainter 和 QPaintDevice 之间,通常对开发人员是透明的。除非需要自定义一个设备,否则是不需要关心 QPaintEngine 这个类的。
  • 因此,我们可以把 QPainter 理解成画笔;把 QPaintDevice 理解成使用画笔的地方,比如纸张、屏幕等;而对于纸张、屏幕而言,肯定要使用不同的画笔绘制,为了统一使用一种画笔,我们设计了 QPaintEngine 类,这个类让不同的纸张、屏幕都能使用一种画笔。
  • 下图给出了这三个类之间的层次结构:

在这里插入图片描述

  • 由这个层次结构可知,QT 的绘图系统实际上是,使用 QPainter 在 QPainterDevice 上进行绘制,它们之间使用 QPaintEngine 进行通讯(也就是翻译 QPainter 的指令)。

2. 画背景图

  • 在使用 QT 进行窗口绘图时,一定要选择 QWidget。

在这里插入图片描述

  • 在绘图事件当中,我们需要注意的是:
  • (1) 在主窗口头文件 widget.h 当中的 protected 下进行重写绘图事件的定义。
  • (2) 如果我们想要在窗口绘图,就必须放在绘图事件里实现。
  • (3) 当窗口需要重绘的时候,也就是窗口的状态发生改变,就像我们点击按钮,调整窗口的大小使其发生变化等操作,绘图事件会内部自动调用。
  • 当我们进行绘图事件构造函数的编写时,通过调用帮助文档(如下图所示),得知需要指定一个绘图设备,指定当前设备使用 this 指针即可。

在这里插入图片描述

  • 对于绘图事件当中,绘图设备的指定有如下方法:
  • 方法一:QPainter p(this);然后直接进行绘图操作。
  • 方法二:首先,创建画家对象 QPainter p;然后指定当前窗口为绘图设备 p.begin(this);但是需要在结束时使用 p.end();在 begin 和 end 之间进行绘图操作,p.drawxxx()。
  • 在上述工作完成后,开始进行背景图的绘制。背景图的绘制函数为:
    //画背景图
    p.drawPixmap(0,0,width(),height(),QPixmap("../tuoian/5.jpg"));
    //p.drawPixmap(rect(),QPixmap("../tuoian/5.jpg"));
  • 在我们一般背景图的绘制过程当中,通常是窗口有多大就绘制多大。因此,从 0,0 坐标开始,也就是窗口的左上角,然后选择窗口的宽度函数 width() 和窗口的高度函数 height(),最后定义图片的标签,这里需要注意的是,图片所在的路径要与代码所在的上一级路径相同,不要放到代码所在的文件夹当中,除非是资源,否则会看不到图片。路径放置如下图所示:

在这里插入图片描述

  • 得到如下实现结果:

在这里插入图片描述

  • 当我们用鼠标更改图片大小时,背景图不会发生变化。

在这里插入图片描述

3. 简单绘图

  • 记住要先画背景,在画其他的,否则会被背景覆盖。
  • 在绘图函数中不要进行太过于复杂的数据处理,否则程序运行很慢。
  • 画直线:这四个参数分别表示起点的 x 坐标和 y 坐标,终点的 x 坐标和 y 坐标。
    //画直线
    p.drawLine(50,50,150,50);
    p.drawLine(50,50,50,150);

在这里插入图片描述

  • 在这里,我们发现画的直线有点窄,可能会导致在实际情况当中看不清。因此,我们要定义一个画笔。
  • 画笔:画笔的头文件是 QPen ,这里的宽度单位是像素。当设置好画笔的线宽之后,仍需将把画笔交给画家,这样我们设置的线宽才会发生作用。
    //定义画笔
    QPen pen;
    pen.setWidth(5);//设置线宽
    
    //把画笔交给画家
    p.setPen(pen);

在这里插入图片描述

  • 除了对线宽进行设置外,还可以对线的颜色、样式等属性进行设置(具体现象不做演示,只讲方法)。
  • 颜色有两种设置方法:可以直接使用 red、blue 等简单颜色;也可以使用 RGB 对颜色进行设置(这里有一个小技巧,我们可以将鼠标放到设置的颜色上,就会显现出具体的颜色)。

在这里插入图片描述

  • 样式可以通过调用帮助文档,选择我们所需要的(其他的属性也是一样的道理,通过 f1 调用帮助文档查看即可)。

在这里插入图片描述

  • 画图形
  • p.drawRect() 是矩形绘画函数,其参数分别表示起点的 x 坐标,起点的 y 坐标,矩形的长度,矩形的宽度(起点坐标是相对于窗口的右上角而言的)。
  • p.drawEllipse() 是圆形绘画函数,其参数分别表示圆心所在点的坐标,水平上圆的半径,垂直上圆的半径(当水平半径和垂直半径相同时就是圆,不同就是椭圆)。
    //画矩形
    p.drawRect(150,150,100,50);
    
    //画圆
    p.drawEllipse(QPoint(150,150),50,25);

在这里插入图片描述

  • 在这里我们发现,只有所画图形的轮廓,如果我们想要将其内部进行填充,就需要使用画刷工具。
  • 画刷:画刷的头文件是 QBrush 。画刷的颜色和样式设置方法与画笔相同,在此就不过多赘述了。将画刷的各项属性设置完成后,还需将画刷交给画家,这样子才可以正确使用。
    //创建画刷对象
    QBrush brush;
    brush.setColor(Qt::red);//设置简单颜色
    brush.setStyle(Qt::Dense1Pattern);//设置样式
    
    //把画刷交给画家
    p.setBrush(brush);

在这里插入图片描述

4. 手动刷新窗口

  • 手动刷新窗口,需要我们对窗口进行重绘。其现象应该是当我们按下按钮,整个窗口进行重绘,图形按指定方式进行移动,因此,要先在 ui 界面上放置一个按钮,并将按钮转到槽函数,单击 on_pushButton_clicked() 函数即可。代码和实现现象如下所示:
void Widget::on_pushButton_clicked()
{
    x+=20;//每点击一下水平向右移动20
    if(x>width())
    {
        x=0;
    }
    
    //刷新窗口,让窗口重绘,整个窗口都刷新
    update();//间接调用paintEvent()
}
  • 这里需要注意的是,update() 不要放在 paintEvent() 函数下,否则会造成死循环。

在这里插入图片描述
在这里插入图片描述

二、绘图实现代码

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:
    //重写绘图事件,虚函数
    //如果在窗口绘图,必须放在绘图事件里实现
    //绘图事件内部自动调用,窗口需要重绘的时候(窗口状态改变,例如:点击按钮,窗口大小变化)
    void paintEvent(QPaintEvent *);

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    int x;
};

#endif // WIDGET_H

2. 主窗口头文件 widget.cpp

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

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

    x=0;//初始坐标设置为0
}

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

void Widget::paintEvent(QPaintEvent *)
{
    // 方法一:
    //QPainter p(this);

    //方法二:
    QPainter p; //创建画家对象
    p.begin(this); //指定当前窗口为绘图设备
    //begin和end之间是绘图操作
    //p.drawxxx();

    //画背景图
    p.drawPixmap(0,0,width(),height(),QPixmap("../tuoian/5.jpg"));
    //p.drawPixmap(rect(),QPixmap("../tuoian/5.jpg"));

    //定义画笔
    QPen pen;
    pen.setWidth(5);//设置线宽
    //pen.setColor(Qt::red);//设置简单颜色
    pen.setColor(QColor(124,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("‪../tuoian/6.jpg"));

    p.end();

}

void Widget::on_pushButton_clicked()
{
    x+=20;//每点击一下水平向右移动20
    if(x>width())
    {
        x=0;
    }

    //刷新窗口,让窗口重绘,整个窗口都刷新
    update();//间接调用paintEvent()
}

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

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

相关文章

【Python机器学习】卷积神经网络卷积层、池化层、Flatten层、批标准化层的讲解(图文解释)

卷积神经网络 卷积神经网络&#xff08;convolutional neural network, CNN&#xff09;在提出之初被成功应用于手写字符图像识别&#xff0c;2012年的AlexNet网络在图像分类任务中取得成功&#xff0c;此后&#xff0c;卷积神经网络发展迅速&#xff0c;现在已经被广泛应用于…

怎样在Odoo 16中启用完整的财务功能

Odoo是目前市场上最好的ERP软件之一。Odoo提供两种类型的版本&#xff0c;社区版和企业版。Odoo社区版是由开源软件支持的免费基本版。Odoo社区版本中没有一些模块和功能。但企业版付费版&#xff0c;升级版更适合更高的价值。Odoo企业版具有无限的功能支持和完整的功能。性能和…

「集合底层」深入浅出HashMap底层源码

「集合底层」深入浅出HashMap底层源码 一、HashMap介绍 HashMap底层采用了哈希表&#xff0c;而哈希表是由数组和链表实现的。数组和链表各有自己的特点&#xff1a; 数组&#xff1a;占用空间连续。 寻址容易&#xff0c;查询速度快。但是&#xff0c;增加和删除效率非常低…

倒序打印链表

在做这个题的时候我闹了一个大笑话&#xff0c;我用了反转链表做&#xff0c;哈哈哈哈&#xff0c; 这个题目思路很简单&#xff0c;用到了数组的头插法&#xff0c;注意题目要求返回数组 遍历链表&#xff0c;将链表的val放到数组中 下面来看代码 import java.util.ArrayLis…

flash基础知识

flash基础手册一、flash概念&#xff08;一&#xff09;特性&#xff08;二&#xff09;FLASH的块/扇区/页关系&#xff08;三&#xff09;常用FLASH型号大小&#xff08;四&#xff09;常用FLASH擦写规则&#xff08;五&#xff09;存储器类型参考二、与其他类型存储器件对照&…

PDF文件怎么加密?推荐3种方法给你

在我们的工作学习上&#xff0c;应该有不少人都需要使用到PDF文件格式&#xff0c;毕竟这个格式它兼容性较广&#xff0c;且不易编辑&#xff0c;能较好的保存文件。不过&#xff0c;我们有时为了不让它被其它人随意查看&#xff0c;会给这个文件进行加密的操作。那你们知道如何…

python实现基于TNDADATASET的人体行为识别

首先来看下TNDADATASET&#xff1a; 随便打开一个文件简单看下如下所示&#xff1a; 可以大概推测出来&#xff0c;这里面不同维度的数据集应该是由不同的穿戴式传感器采集得到的&#xff0c;最后一列的class表示的是当前的行为类型。 在我之前的博文里面已经做过了相关的工作…

计算机毕设Python+Vue养老机构管理信息系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Sigrity常见问题解决方法(持续更新)

Sigrity常见问题解决方法&#xff08;持续更新&#xff09; 1.使用SpeedEM仿真时&#xff0c;报placement error 错误信息如下&#xff1a; 该问题是因为Mesh设置的过大&#xff0c;导致via和note在同一个mesh网格上存在粘连 解决方法是&#xff1a;将mesh进行auto设置 2…

鲍鱼年龄预测 knn svm 逻辑回归

数据&#xff1a; M,0.455,0.365,0.095,0.514,0.2245,0.101,0.15,15 M,0.35,0.265,0.09,0.2255,0.0995,0.0485,0.07,7 F,0.53,0.42,0.135,0.677,0.2565,0.1415,0.21,9 M,0.44,0.365,0.125,0.516,0.2155,0.114,0.155,10 I,0.33,0.255,0.08,0.205,0.0895,0.0395,0.055,7 I,0.425…

基于pytorch搭建CNN 人像口罩识别检测项目

项目介绍 我们将使用 CNN (卷积神经网络)和机器学习分类器创建一个检测一个人是否戴着口罩的分类器。它将检测一个人是否戴着口罩。 我们将从头开始学习,我将对每一步进行解释。我需要你对机器学习和数据科学有基本的了解。我已经在本地 Windows 10 机器上实现了它,如果你…

深入浅出JVM(七)之执行引擎的解释执行与编译执行

执行引擎 hotspot执行引擎结构图 执行引擎分为解释器、JIT即时编译器以及垃圾收集器 执行引擎通过解释器/即时编译器将字节码指令解释/编译为对应OS上的的机器指令 本篇文章主要围绕解释器与即时编译器&#xff0c;垃圾收集器将在后续文章解析 解释执行与编译执行 Java虚拟机…

方向图与天线增益

目录 一、方向图 二、增益 一、方向图 天线的方向性是指天线向一定方向辐射电磁波的能力。对于接收天线而言&#xff0c;方向性表示天线对不同方向传来的电磁波具有不同的接收能力。天线的方向性通常用方向图来表示。 在数学里&#xff0c;球坐标系是一种利用球坐标表示一个点…

Linux学习-90-Tomcat下载安装(tar压缩包)

17.20 Tomcat下载安装&#xff08;tar压缩包&#xff09; 访问apache官网下载tomcat压缩包。访问以下链接进行下载tomcat-8.5.83版本&#xff0c;高版本的tomcat存在一些问题影响使用&#xff0c;然后使用 Xftp 上传到/usr/local/src目录中或者使用wget命令直接到/usr/local/s…

SpringBoot:模块探究之spring-boot-cli

Spring Boot CLI 是运行 SpringBoot 命令的命令行工具&#xff0c;能够帮助你快速的构建 Spring Boot 项目。只需要编写简单的 groovy 脚本&#xff0c;即可用最少的代码构建并运行一个完整的 Spring Boot 项目。 Spring Boot CLI 为 SpringCloud 提供了 SpringBoot 命令行功能…

Java面试--CAS

这里写目录标题一、概念二、CAS 如何保证原子性2.1、总线锁定2.2、缓存锁定二、底层原理三、CAS典型应用四、CAS问题4.1、循环时间长&#xff0c;开销很大4.2、只能保证一个共享变量的原子操作4.3、引出来 ABA 问题一、概念 判断内存中某个位置的值是否为预期值&#xff0c;如…

Bootstrap5 表单浮动标签

默认情况下&#xff0c;标签内容一般显示在 input 输入框的上方&#xff1a; 使用浮动标签&#xff0c;可以在 input 输入框内插入标签&#xff0c;在单击 input 输入框时使它们浮动到上方 Bootstrap 实例 <div class"form-floating mb-3 mt-3"> <input ty…

uni.requestPayment使用

前言&#xff1a;由于uni.requestPayment没有封装H5支付方法&#xff0c;我自己封装了统一方法可以多端适用。 代码如下&#xff1a; 有两种方法&#xff1a; 方法1&#xff1a;安装 jweixin-module 包&#xff0c;我的是1.6.0版本->引入->使用 方法2&#xff1a;使用微…

51单片机实训day2——创建Keil工程(一)

以管理员身份打开软件&#xff01;&#xff01;&#xff01;以管理员身份打开软件&#xff01;&#xff01;&#xff01;以管理员身份打开软件&#xff01;&#xff01;&#xff01; 内 容&#xff1a;Keil工程创建 学 时&#xff1a;2学时 知识点&#xff1a;开发固件库介绍…

【Linux】进程替换与shell的模拟实现

目录 一、进程替换 1.1 进程替换的概念 1.2 替换函数 二、命令行解释器-Shell 2.1 shell的实现与运行 2.2 步骤讲解 一、进程替换 1.1 进程替换的概念 当我们使用 fork 函数创建子进程后&#xff0c;父子进程各自执行父进程代码的一部分。那如果创建的子进程想要执行一…