【Qt】控件概述(3)—— 显示类控件

显示类控件

  • 1. QLabel——标签
    • 1.1 setPixmap设置图片
    • 1.2 setAlignment设置文本对齐方式
    • 1.3 setWordWrap设置自动换行
    • 1.4 setIndent设置缩进
    • 1.5 setMargin设置边距
    • 1.6 body
  • 2. QLCDNumber
    • 2.1 使用QTimer实现一个倒计时效果
    • 2.2 使用循环的方式实现倒计时
  • 3. QProgressBar——进度条
  • 4. QCalendarWidget——日历

1. QLabel——标签

QLabel可以用来显示文本和图片:

属性说明
textQLabel中的文本
textFormat文本格式:1:Qt::PlaintText纯文本,2:RichText富文本,3:MarkDownText markdown格式,4:Qt:AutoText根据文本内容自动决定文本格式
pixmapQLabel内的图片
scaldContents设置未true表示自动拉伸填充QLabel,设置为false则不会自动填充
alignment表示对齐方式,可以设置为水平对齐和垂直对齐
wordWrap自动换行设置,设置为true表示开启,设置为false表示不开启
indent文本缩进,水平和垂直都可以生效
margin表示文本和边框之间的距离,在上下左右四个方向生效
openExternalLinks是否允许打开一个外部链接(当Qlabel涉及到url的时候)
buddy给QLabel关联一个“伙伴”,当点击QLabel时就会激活对应的“伙伴”

1.1 setPixmap设置图片

代码样例:Label显示图片
虽然前面讲的QPushButton也可以通过setIcon的方式进行添加图片,但是大多数时候我们更希望使用QLabel来进行添加一个更单纯的一个图片。

  1. 首先同样讲图片以qrc的方式添加到Qt中
  2. 创建Label,并可以通过pixmap进行添加图片
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QLabel* label = new QLabel(this);
    // 设置标签的大小和Widget窗口的大小是一样的
    QRect rect = this->geometry();
    label->setGeometry(0, 0, rect.width(), rect.height());
    // 插入图片并设置图片大小
    QPixmap pixmap(":/qt.jpg");
    pixmap = pixmap.scaled(rect.width(), rect.height());
    // 也可以直接使用自动填充,让图片自动贴合标签的大小
	// label->setScaledContents(true);
    label->setPixmap(pixmap);
}

但是这个时候我们是可以对Widget的窗口进行调整大小的,而在我们进行调整大小的时候,我们的标签是不会跟着改变的,所以这里我们需要提供一个事件。也就是说当我们在调整Widget的时候QWidget会触发一个事件resizeEvent事件,也就是说当Widget窗口大小发生变化的时候QWidget 会自动进行调用,而这个时候我们想要Widget进行调用,就可以在Widget中重写这个resizeEvent实现多态,这样只要窗口发生变化就会通过多态调用Widget中的resizeEvent(这个事件我们后面会详细进行讲解),所以我们就可以自定义函数来完成这一操作。

在这里插入图片描述

// 在widget.h中添加函数声明
void resizeEvent(QResizeEvent *event); // 这个是QWidget中有的
void Widget::resizeEvent(QResizeEvent *event)
{
    label->setGeometry(0, 0, event->size().width(), event->size().height());
    label->setScaledContents(true);
    qDebug() << event->size();
}

1.2 setAlignment设置文本对齐方式

首先为了我们方便观察,我么需要给label设置一个外边框,我们可以在ui界面中进行设置。
在这里插入图片描述

QFrame是QLabel的父类,其中frameShape属性用来设置边框属性。

  • QFrame::Box :矩形边框
  • QFrame::Panel :带有可点击区域的⾯板边框
  • QFrame::WinPanel :Windows风格的边框
  • QFrame::HLine :水平线边框
  • QFrame::VLine :垂直线边框
  • QFrame::StyledPanel :带有可点击区域的⾯板边框,但样式取决于窗口主题
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->label->setText("这是一个水平居中和垂直居中");
    // 设置文本的对齐方式
    // 设置方式 水平方向 | 垂直方向
    ui->label->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
}

而设置垂直方向和水平方向的对齐方式其实就是宏。

enum AlignmentFlag {
        AlignLeft = 0x0001, 
        AlignLeading = AlignLeft,
        AlignRight = 0x0002,
        AlignTrailing = AlignRight,
        AlignHCenter = 0x0004,
        AlignJustify = 0x0008,
        AlignAbsolute = 0x0010,
        AlignHorizontal_Mask = AlignLeft | AlignRight | AlignHCenter | AlignJustify | AlignAbsolute,

        AlignTop = 0x0020,
        AlignBottom = 0x0040,
        AlignVCenter = 0x0080,
        AlignBaseline = 0x0100,
        // Note that 0x100 will clash with Qt::TextSingleLine = 0x100 due to what the comment above
        // this enum declaration states. However, since Qt::AlignBaseline is only used by layouts,
        // it doesn't make sense to pass Qt::AlignBaseline to QPainter::drawText(), so there
        // shouldn't really be any ambiguity between the two overlapping enum values.
        AlignVertical_Mask = AlignTop | AlignBottom | AlignVCenter | AlignBaseline,

        AlignCenter = AlignVCenter | AlignHCenter
    };

在这里插入图片描述

1.3 setWordWrap设置自动换行

如果我们使用在label中输入了一行很长的文本而没有自动换行,就会导致部分文本被覆盖而无法显示。

ui->label->setText("这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,");

在这里插入图片描述

ui->label->setText("这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,");
ui->label->setWordWrap(true);

在这里插入图片描述

1.4 setIndent设置缩进

一般我们在书写word的时候使用的都是首行缩进,但是在Qt中,这里的缩进是对所有行都适用的,不单单是首行缩进

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->label->setText("这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,");
    ui->label->setWordWrap(true);
    ui->label->setIndent(50); // 单位像素
}

在这里插入图片描述

1.5 setMargin设置边距

我们先直接讲对齐方式改为水平左对齐,垂直上对其。

ui->label->setText("这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,");
ui->label->setWordWrap(true);
ui->label->setAlignment(Qt::AlignLeft | Qt::AlignTop);

在这里插入图片描述
设置margin后

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->label->setText("这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,这是一个自动换行机制,");
    ui->label->setWordWrap(true);
    ui->label->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    ui->label->setMargin(20);
}

在这里插入图片描述

1.6 body

我们可以创建两个label和两个radioButton,将其两两关联。然后可以使用快捷键的方式进行选择。
在这里插入图片描述

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->label->setBuddy(ui->radioButton);
    ui->label_2->setBuddy(ui->radioButton_2);
}

这样就可以使用 alt + a选择1,alt+b选择2了。而如果想要做到这样的效果也需要遵循一些规则,也就是使用&A(& + 快捷键)这样的形式才可以做到。

2. QLCDNumber

QLCDNumber是一个专门用来显示数字的控件。

属性说明
intValueQLCDNumber显示数字的值(int)
valueQLCDNumber显示的数字值(double),和intValue是联动的,例如value为1.2,那么intValue就是1,另外value和intValue的方法名在位display,而不是setValue或者setValue了
digitCount显示数字的位数
mode显示数字的模式。1:QLCDNubmer::Dec,十进制。2:QLCDNubmer::Hex,十六进制。3:QLCDNubmer::Bin,二进制。4:QLCDNubmer::Oct,八进制。
segmentStyle设置显示风格,1:QLCDNumber::Flat,平面显示风格,数字呈现在一个平坦的表面上。2:QLCDNumber::Outline,轮廓显示风格,数字具有轮廓和阴影效果。3:QLCDNumber::Filled,填充风格,数字可以填充颜色与背景进行区分。

2.1 使用QTimer实现一个倒计时效果

代码样式:显示一个倒计时效果
在此之前介绍一个了QTimer类,这个类是Qt封装的一个定时器,可以通过start方法启动定时器,并通过传递参数的方式进行设定定时周期。而QTimer中有一个信号timeout,会根据周期定期的触发timeout信号,这样我们可以把周期设置为1秒,就可以首先一个简单的定时器了。

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 创建一个定时器类
    time = new QTimer(this);
    ui->lcdNumber->display(10);
    connect(time, &QTimer::timeout, this, &Widget::handle);
    // 启动定时器
    time->start(1000); // 单位毫秒
}

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

void Widget::handle()
{
    // 获取当前lcdNumnber值
    int num = ui->lcdNumber->value();
    if (num <= 0){
        // 关闭定时器
        time->stop();
        return;
    }
    // 设置值
    ui->lcdNumber->display(num - 1);
}

2.2 使用循环的方式实现倒计时

针对上述存在两个问题。

  1. 我们先使用最为平常的for循环进行实现,使用Sleep的方式实现。而Sleep是windows的需要包含"windows.h",那是Qt并没有相关的api,但是C++11 中引路了sleep是thread库中的sleep_for
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->lcdNumber->display(10);
    int value = ui->lcdNumber->value();
    while(true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        if (value <= 0){
            break;
        }
        value -= 1;
        ui->lcdNumber->display(value);
    }
}

这样明显是没法显示出来的,因为whiel循环是在Widget的构造函数中实现的,而窗口的显示是在Widget类实例化后使用w.show()进行实现的,所以是等到while循环结束后,才会调用窗口显示函数进行窗口展示。

  1. 所以这里我们就想到使用子线程来进行修改
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->lcdNumber->display(10);
    std::thread t([this](){
        int value = ui->lcdNumber->value();
        while(true)
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            if (value <= 0){
                break;
            }
            value -= 1;
            ui->lcdNumber->display(value);
        }
    });
}

上述通过子线程的方式修改GUI上的内容同样是不行的,在Qt中规定,任何对GUI上内容的操作,必须是主线程中完成的。这样的约定主要是因为GUI中的状态往往是牵一发东全身,就需要同步的对其他内容进行调整。比如调整了某个元素的尺寸,就可能影响到内部的文字位置,或者其他元素的位置.这里⼀连串的修改,都是需要按照⼀定的顺序来完成的.由于多线程执行的顺序无法保障,因此Qt从根本上禁止了其他线程修改GUI状态,避免后续的⼀系列问题.

3. QProgressBar——进度条

核心属性:

属性说明
minimum进度条最小值
maximum进度条最大值
value进度条当前值,同上
alignment文本在进度条中的对齐方式. 同上
textVisible进度条的数字是否可见
orientation进度条的方向是水平还是垂直
invertAppearance是否是朝反方向增长进度
textDirection文本的朝向.
format展示的数字格式. 1:%p :表示进度的百分比(0-100),2:%v :表示进度的数值(0-100),3:%m :表示剩余时间(以毫秒为单位),4:%t :表示总时间(以毫秒为单位)

代码样例:实现一个进度条

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    time = new QTimer(this);
    connect(time, &QTimer::timeout, this, &Widget::handle);
    time->start(100);
}

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

void Widget::handle()
{
    int value = ui->progressBar->value();
    if (value >= 100){
        time->stop();
        return;
    }
    ui->progressBar->setValue(value + 1);
}

这里我们看到Widget.h这块

#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 handle();

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

从上述代码中我们可以发现一个小细节,就是Widget.h中明明使用了QTimer类,但是并没有包含QTimer头文件#include < QTimer >,而且还没有编译报错。这是应为Qt做了一些特殊处理,在Qt中专门有一个头文件,这个头文件包含了Qt中所有类的“前置声明”形如(class QTimer; class QWidget……),而这个头文件一般不会直接接触到,而是包含在其他的Qt的头文件中,所以在继承的时候就间接的包含这个头文件,所以就可以使用一些类在头文件中声明各种类的指针或者了引用。

而这样的做的目的就是减少编译时的运行时间,应为在C/C++编译期间是要讲头文件进行展开的,而对于一个大型的项目来讲,不乏会包含大量的头文件,而这也间接的增加了编译的时间,所以在头文件声明之处就可以使用这样的前置声明的技术来减少头文件的包含,也可以做到间接减少编译的时间。

但是在C++20后就开始使用module来代替#include,这样也是为了减少编译时的时间消耗。

同样进度条也是可以设置样式的。可以通过ui界面的熟悉面板进行设置,也可以使用代码进行设置。
在这里插入图片描述

4. QCalendarWidget——日历

核心属性

属性说明
selectDate当前选中的日期,返回一个QDate类型
minimumDate最小日期
maximumDate最大日期
firstDayOfWeek每周的第⼀天(也就是日历的第⼀列)是周几.
gridVisible是否显示表格的边框
selectionMode是否允许选择日期
navigationBarVisible日历上方标题是否显示
horizontalHeaderFormat日历上方标题显示的日期格式
verticalHeaderFormat日历第⼀列显示的内容格式
dateEditEnabled是否允许日期被编辑

重要信号

信号说明
selectionChanged(const QDate&)当选中的日期发生改变时发出
activated(const QDate&)当双击⼀个有效的日期或者按下回车键时发出,形参是⼀个QDate类型,保存了选中的日期
currentPageChanged(int, int)当年份月份改变时发出,形参表示改变后的新年份和月份
void Widget::on_calendarWidget_selectionChanged()
{
    QDate date = ui->calendarWidget->selectedDate();
    ui->label->setText(date.toString());
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【工程测试技术】第6章 信号处理初步,频谱分析,相关系数

目录 6.1 数字信号处理的基本步骤 6.2 离散信号及其频谱分析 6.2.1 概述 6.2.2 时域采样、混叠和采样定理 6.2.3 量化和量化误差 6.2.4 截断、泄漏和窗函数 6.2.5 频域采样、时域周期延拓和栅栏效应 6.2.6 频率分辨率、整周期截断 6.3 相关分析及其应用 6.3.1 两…

【C++】--类与对象(1)

&#x1f9c7;个人主页: 起名字真南 &#x1f32d;个人专栏:【数据结构初阶】 【C语言】 【C】 目录 1 类的定义1.1 类定义格式1.1.1 Stack类1.1.2 Date类1.1.3 Struct格式 1.2 访问限定符1.3 类域 2 实例化2.2 对象大小 3 this指针 1 类的定义 1.1 类定义格式 1 class为定义…

解决磁盘负载不均——ElasticSearch 分片分配和路由设置

ES 分片分配&#xff08;Shard Allocation&#xff09;时间点&#xff1a; 初始恢复&#xff08;Initial Recovery&#xff09;副本分配&#xff08;Replica Allocation&#xff09;重平衡&#xff08;Rebalance&#xff09;节点添加或移除 小结&#xff1a; 准备移除节点时&a…

【Golang】关于Go语言字符串转换strconv

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

k8s-集群部署1

k8s-集群部署1 一、基础环境准备二、docker环境准备三、k8s集群部署1.kubeadm创建集群2.使用kubeadm引导集群 总结 一、基础环境准备 首先&#xff0c;需要准备三个服务器实例&#xff0c;这里我使用了阿里云创建了三个实例&#xff0c;如果不想花钱&#xff0c;也可以在VM上创…

1panel申请https/ssl证书自动续期

参考教程 https://hin.cool/posts/sslfor1panel.html #Acme 账户 #1panel.腾讯云dns账号 这里有一步不需要参考,腾讯云dns账号,就是子帐号授权 直接控制台搜索 访问管理 创建用户 授权搜索dns,选择第一个 点击用户名,去掉AdministratorAccess权限 5.点击api密钥生成即可…

CSS3练习--电商web

免责声明&#xff1a;本文仅做分享&#xff01; 目录 小练--小兔鲜儿 目录构建 SEO 三大标签 Favicon 图标 布局网页 版心 快捷导航&#xff08;shortcut&#xff09; 头部&#xff08;header&#xff09; logo 导航 搜索 购物车 底部&#xff08;footer&#xff0…

初学51单片机之I2C总线与E2PROM二

总结下上篇博文的结论&#xff1a; 1&#xff1a;ACK信号在SCL为高电平期间会一直保持。 2&#xff1a;在字节数据传输过程中如果发送电平跳变&#xff0c;那么电平信号就会变成重复起始或者结束的信号。&#xff08;上篇博文的测试方法还是不能够明确证明这个结论&#xff0…

字符串和字符数组(2)

6.求字符串长度 C语言中有一个库函数叫strlen&#xff0c;这个函数是专门用来求字符串长度的。strlen的使用需要包含一个头文件string.h。 strlen函数统计的是字符串中\0之前的字符个数&#xff0c;所以传递给strlen函数的字符串中必须得包含\0. 请看代码&#xff1a; #inc…

数据结构 ——— 单链表oj题:链表分割(带哨兵位单向不循环链表实现)

目录 题目要求 手搓简易单链表 代码实现 题目要求 现有一链表的头指针 ListNode* head &#xff0c;给一定值 x &#xff0c;编写一段代码将所有小于 x 的节点排在其余节点之前&#xff0c;且不能改变原来的数据顺序&#xff0c;返回重新排列后的链表的头节点 举例说明&a…

免费送源码:Javaspringboot++MySQL springboot 社区互助服务管理系统小程序 计算机毕业设计原创定制

摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受居民的喜爱&#xff0c;社区互助服务管理系统小程序被居民普遍使用&#xff0c;为…

macOS编译和运行prometheus2.54

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 本文详述了在macOS(M2芯片)上编译和运行prometheus2.54版本的过程&#xff0c;以及安装node_exporter和grafana并使用prometheus指标进行展示 本地…

Redis:zset类型

Redis&#xff1a;zset类型 zset命令ZADDZCARDZCOUNTZRANGEZREVRANGEZRANGEBYSCOREZREVRANGEBYSCOREZPOPMAXBZPOPMAXZPOPMINBZPOPMINZRANKZREVRANKZSCOREZREMZREMRANGEBYRANKZREMRANGEBYSCOREZINCRBY 集合间操作ZINRERSTOREZUNIONSTORE 内部编码ziplistskiplist 在Redis中&…

单片机的两种看门狗原理解析——IWDG和WWDG

一、IWDG独立开门狗的主要性能 计时机制&#xff1a; 递减计数器 独立开门狗的初始频率&#xff1a; LSI低速内部时钟&#xff1a;RC震荡器&#xff0c;40kHz 独立开门狗是以LSI为初始频率的&#xff0c;所以独立开门狗的初始时钟频率取决与单片机本身&#xff0c;因此在使…

[每周一更]-(第117期):硬盘分区表类型:MBR和GPT区别

文章目录 1. **支持的磁盘容量**2. **分区数量**3. **引导方式**4. **冗余和数据恢复**5. **兼容性**6. **安全性**7. **操作系统支持**8. 对比 国庆假期前补一篇 在一次扫描机械硬盘故障的问题&#xff0c;发现我本机SSD和机械硬盘的分类型不一样&#xff0c;分别是GPT和MBR&a…

Matlab编程示例24:freexyn在b站的读取手写体mnist数据集的matlab代码

1.mnist手写体数据集介绍 手写数字MNIST数据库由60000个示例的训练集和10000个示例的测试集组成。这些数字已进行归一化&#xff0c;每个示例是28*28像素的图片&#xff0c;图片是黑底白字&#xff0c;每个图片的标签就是图片上的数字&#xff0c;数字范围是0~9&#xff0c;总…

记录一次病毒启动脚本

在第一次下载软件时&#xff0c;目录中配了一个使用说明&#xff0c;说是需要通过start.bat 这个文件来启动程序&#xff0c;而这个 start.bat 就是始作俑者&#xff1a; 病毒作者比较狡猾&#xff0c;其中start.bat 用记事本打开是乱码&#xff0c;但是可以通过将这个批处理…

小程序 uniapp+Android+hbuilderx体育场地预约管理系统的设计与实现

目录 项目介绍支持以下技术栈&#xff1a;具体实现截图HBuilderXuniappmysql数据库与主流编程语言java类核心代码部分展示登录的业务流程的顺序是&#xff1a;数据库设计性能分析操作可行性技术可行性系统安全性数据完整性软件测试详细视频演示源码获取方式 项目介绍 用户 注册…

探索 Python 虚拟环境的奥秘:virtualenv 的魔法世界

文章目录 探索 Python 虚拟环境的奥秘&#xff1a;virtualenv 的魔法世界背景&#xff1a;为何选择 virtualenv&#xff1f;虚拟环境的守护者&#xff1a;virtualenv 是什么&#xff1f;安装 virtualenv&#xff1a;简单几步&#xff0c;开启隔离之旅掌握 virtualenv 的基本用法…

LC刷题专题:堆、大顶堆、小顶堆

文章目录 692. 前K个高频单词215. 数组中的第K个最大元素2336、无限集中的最小数字 这篇文章以后记录自己刷到的题目中与堆有关的。 692. 前K个高频单词 这个题目整体不难&#xff0c;是前k个高频元素的改进版&#xff0c;只需要在创建小顶堆时执行排序规则即可。如果出现次数…