目录
[1.2 Qt的优点](#1.2 Qt的优点)
[5.Qt Designer](#5.Qt Designer)
[9.1 connect](#9.1 connect)
[9.2 自定义槽函数](#9.2 自定义槽函数)
[9.3 自定义信号](#9.3 自定义信号)
[9.4 断开信号链接(disconnect)](#9.4 断开信号链接(disconnect))
[10.1 QWidget](#10.1 QWidget)
[10.1.1 QWidget的enable属性](#10.1.1 QWidget的enable属性)
[10.1.2 QWidget的geometry属性](#10.1.2 QWidget的geometry属性)
[10.1.3 WindowFrame的影响](#10.1.3 WindowFrame的影响)
[10.1.4 QWidget的windowTitle属性](#10.1.4 QWidget的windowTitle属性)
[10.1.5 QWidget的windowlcon属性](#10.1.5 QWidget的windowlcon属性)
[10.1.6 QWidget的WindowOpacity属性](#10.1.6 QWidget的WindowOpacity属性)
[10.1.7 QWidget的cursor属性](#10.1.7 QWidget的cursor属性)
[10.1.8 QWidget的font属性](#10.1.8 QWidget的font属性)
[10.1.9 QWidget的toolTip属性](#10.1.9 QWidget的toolTip属性)
[10.1.10 QWidget的focusPolicy属性](#10.1.10 QWidget的focusPolicy属性)
[10.1.11 QWidget的styleSheet属性](#10.1.11 QWidget的styleSheet属性)
[10.2 Button按键](#10.2 Button按键)
[10.2.1 QPushButton添加图标](#10.2.1 QPushButton添加图标)
[10.2.2 QPushButton添加快捷](#10.2.2 QPushButton添加快捷)
[10.2.3 QRadioButton的使用](#10.2.3 QRadioButton的使用)
[10.2.4 QCheckBox的使用](#10.2.4 QCheckBox的使用)
[10.3 QLabel](#10.3 QLabel)
[10.3.1 QLanel文本显示方式](#10.3.1 QLanel文本显示方式)
[10.3.2 QLanel设置图片](#10.3.2 QLanel设置图片)
[10.3.3 QLabel设置自动换行,边距,缩进](#10.3.3 QLabel设置自动换行,边距,缩进)
[10.3.4 QLabel设置伙伴](#10.3.4 QLabel设置伙伴)
[10.4 QLCDNumber](#10.4 QLCDNumber)
[10.5 ProgressBar](#10.5 ProgressBar)
[10.6 QCalendarWidget](#10.6 QCalendarWidget)
[10.7 QLineEdit](#10.7 QLineEdit)
[10.7.1 QLineEdit的使用](#10.7.1 QLineEdit的使用)
[10.7.2 QLineEdit属性](#10.7.2 QLineEdit属性)
1.QT的诞生史
Qt 是一个跨平台的 C++ 应用程序开发框架,由挪威的 Trolltech 公司创立。以下是 Qt 的主要发展历程:
1.创建阶段(1991-1992年):
Qt 开始于 1991 年,最初是为了满足挪威电讯公司(Telenor)的内部需要而开发的。Trolltech 公司的创始人之一 Haavard Nord和Eirik Chambe-Eng,都是在Telenor工作时开发了 Qt。1992 年 Trolltech 公司正式成立,将 Qt 作为主要的产品和开发平台。
2.商业化(1994 年):
Trolltech 公司推出了 Qt 1.0 版本,正式将其作为商用软件发布。Qt 1.0 支持 X11,但在 Windows 平台上尚未提供支持。
3.跨平台支持(1995年):
Qt 2.0 在 1995 年发布,这是 Qt 第一个支持跨平台开发的版本,同时在 Windows 和 X11 上实现了兼容。这使得开发者可以编写一次代码,然后在不同的平台上进行部署而无需大量修改。
4.开源化(1999年):
Trolltech 公司于 1999 年将 Qt 开源,并发布了 Qt 2.3 版本。这一举措使得开发人员可以自由获取和使用 Qt,加速了 Qt 在各种平台上的普及。
5.KDE 的采用(2000年):
KDE(K Desktop Environment)是一个流行的 Linux 桌面环境,于 2000 年开始采用 Qt 作为主要的开发工具包,这加速了 Qt 在 Linux 社区的普及。
6.版本升级(2005年和之后):
随着时间的推移,Qt 经历了多个主要版本的升级和更新,不断增加新的功能和改善性能。Qt 4 和 Qt 5 版本的发布进一步提升了 Qt 在跨平台应用程序开发中的地位。
7.The Qt Company(2012年):
2012 年,Digia 公司收购了 Trolltech 公司,并在 2013 年将 Qt 的开发部门和知识产权转移到了一个新成立的公司,The Qt Company。
8.当前阶段(2021年):
到了今天,Qt 仍然是一个广受欢迎的跨平台开发框架,在不同领域中得到广泛应用,包括桌面应用程序、移动应用程序、嵌入式系统等。The Qt Company 不断推出新版 Qt,提供各种工具和服务来支持开发者的需求,可以说现在的Qt是一位六边形战士。
Qt 的发展经历了多个重要里程碑,一直以来都是开发人员和组织中的首选框架之一,对于跨平台应用程序开发起到了重要的推动作用。
1.2 Qt的优点
* 跨平台,几乎支持所有的平台
* 接口简单,容易上手,学习QT框架对学习其他框架具有很高的参考意义
* 一定程度上简化了内存回收机制
* 开发效率高,能够快速的啊构建应用程序
* 有很好的社区氛围,市场份额在缓慢上升
* 可以进行嵌入式编程
2.安装Qt
其他的方式安装这里并不是很推荐,我们可以直接下载Qt Creator,它已经配置好了所需的编译器以及其他,并不需要我们去手动配置
以下是下载Qt Creator的网址,下载安装即可,一路next下去即可,并没有什么难度
Index of /archive/qt/5.12/5.12.12
3.创建项目
下载安装完成后,我们将会得到这样一个页面
接下来,我们一步一步去创建一个项目
并没有什么难度
4.解读Qt自动生成的代码
//自定义窗口部件的头文件,widget类定义了应用程序的主窗口,其包含
//用户界面和其它江湖元素
#include "widget.h"
//这是我们之前选择QApplication,自己包含的头文件
#include <QApplication>
int main(int argc, char *argv[])
{
//创建一个QApplication对象a,它是Qt应用程序的主要对象
//注:负责处理时间循环和应用程序的整体管理
QApplication a(argc, argv);
//创建一个Widget对象w
//注:调用其构造函数来初始化窗口控件
Widget w;
//显示窗口控件,与之对应的w.hide()关闭显示
w.show();
//启动Qt事件循环,处理用户触发事件,或者定时器等
//exec会一直运行至程序终止,结束后会返回程序状态码
return a.exec();
}
此处是一段简单的Qt程序入口函数,此处创建了一个应用程序对象,自定义窗口控件对象,并最终通过事件循环来驱动整个程序的运行。
直接进入Widget的声明中,我们接着去看。
//防止头文件重复包含,自不必多说
#ifndef WIDGET_H
#define WIDGET_H
//QWidget:创建Qt中控件的基类
#include <QWidget>
//QT_BEGIN_NAMESPACE,QT_END_NAMESPACE:用于定义命名空间,在这个命名空间中
,定义了一个名为ui的命名空间,其中包含一个名为Widget的类。
QT_BEGIN_NAMESPACE
//此处是由 Qt Designer 自动生成,后续会解释什么是 Qt Designer
namespace Ui { class Widget; }
QT_END_NAMESPACE
//Widget类的声明,他继承自Qwidget,表示Widget是一个窗口控件类
//窗口控件:是用户界面的基本组成部分,用于创建和管理用户界面上的各种元素
class Widget : public QWidget
{
//Qt元对象宏,类中声明一个Qt元对象类。
//这个宏使得该类可以使用信号以及槽机制和其他元对象相关的功能
//注:Qt中很多地方都使用了元编程,所谓的元编程,就是代码生成代码的一种编码手段
Q_OBJECT
public:
//widget的构造函数和析构函数
Widget(QWidget *parent = nullptr);
~Widget();
private:
//声明私用成员Ui::Widget *ui;
Ui::Widget *ui;
};
#endif // WIDGET_H
//Widget类的头文件,包含Widget的声明
#include "widget.h"
//包含ui_widget的头文件,是由Qt Designer自动生成的UI头文件
//其中包含一个名为Widget的类,该类包含了UI界面中的所有控件
#include "ui_widget.h"
//widget的构造函数,接收一个QWidget类型的指针作为参数,表示该窗口控件的父类
//在构造函数初始化列表中,首先调用了QWidget类的构造函数,将parent参数传递给
//基类构造函数,然后产生新的Ui::Widget对象,并将其指针赋值给成员变量ui
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
//调用ui所指向的对象setupUi()函数,将当前窗口的空间对象this作为参数传递给该函数。
//setupUi()函数是由Qt Designer自动生成的,用于初始化UI界面中的空间。包括布局,控件大小,位置等
ui->setupUi(this);
}
//析构函数
Widget::~Widget()
{
//释放资源,首先通过delete ui 释放之前构造函数动态分配对象ui 所占的内存空间
delete ui;
}
5.Qt Designer
Qt Designer 是一种可视化界面设计器,用于创建和设计Qt应用程序的用户界面,它允许开发人员通过拖放的操作来快速构建用户界面。无需手动操作,省去了大量代码。Qt Designer集成在Qt Creator 中,是Qt开发环境的一部分。
使用Qt Designer开发,可以轻松完成设计界面布局,添加控件,设置属性和信号槽连接等。Qt Designer 提供了一个直观地用户界面,是的开发人员可以以所见即所得的方式进行界面设计。并且可以实时预览效果。
Qt Designer主要包括以下功能:
1.托方式设计:通过简单的拖放操作,可以快速地将各种控件添加到界面中,并调整它们的大小,位置等
2.属性编辑:可以方便地编辑控件属性,如文本内容,颜色,字体等
3.信号槽编辑:可以直观地设置控价之间的信号槽连接,以实现界面元素之间的交互功能。
4.预览模式:可以实时预览设计效果,以便及时调整和修改
5.自定义控件:可以创建自定义部件和控价,并在界面中使用
6.支持国际化:提供了国际化工具,可以方便进行多种语言界面设计
点击之后我们将得到这样一个界面
6.Qt对象数
Qt 对象树是指在 Qt 应用程序中,各个 QObject 类型对象之间的层次结构关系。在 Qt 中,几乎所有的类都直接或间接继承自 QObject 类,因此 Qt 应用程序中的对象通常都是 QObject 类型的。
就比如我们的Qwidget也是继承自QObgect
Qt 对象树的特点包括:
1.层次结构关系:Qt 对象按照父子关系构成层次结构,形成了树形结构。每个 QObject 对象都可以有一个父对象,也可以有多个子对象。当一个对象被设置为另一个对象的子对象时,它会自动成为后者的子节点,形成层次结构。
2.资源管理:Qt 对象树的存在方便了资源的管理和释放。当父对象被销毁时,它会自动销毁所有的子对象,从而避免了内存泄漏和资源泄漏的问题。这是通过 Qt 中的对象树自动回收机制实现的。
3.信号与槽传播:QObject 类提供了信号与槽机制,用于对象之间的通信。在对象树中,信号和槽的连接可以跨越父子对象之间的边界,使得对象之间的通信更加灵活。
4.对象查找:Qt 提供了一系列方法用于在对象树中查找特定对象,包括通过对象名称、类型、父对象等条件进行查找。
5.父子关系的影响:父子关系不仅影响对象的生命周期管理,还影响了对象的事件传递和属性继承。例如,当父对象接收到事件时,它会将事件传递给所有的子对象;父对象的属性更改也可能会影响到子对象。
在 Qt 应用程序中,通常会利用对象树的特性来组织和管理界面控件、数据模型、线程对象等各种对象,从而实现清晰的代码结构和有效的资源管理。
7.Qt乱码问题
在Qt中提供了很多和c++语法相同的关键字,唯一不同的是在前面加了q,这是一些历史遗留问题,当然,qt中也支持你使用c++的关键字,因为对其本身并没有影响,所以并没有去解决这块问题。相反,当你熟悉Qt还会感觉无比舒服看起来。
在Qt中我们通常不会使用cout等流插入方式进行打印我们的错误信息,而是使用qDebug()来打印,一方面:是因为cout编码一般会因为你的设备不同而格式不同,在windows中通常是 Windows ANSI 编码(例如,CP1252)。而在linux/Unix中则为UTF-8 编码。但在我们的Qt中一般默认输出的是UTF-8,所以我们使用cout打印可能会出现乱码情况。
另一方面:是因为在使用qDebug()打印,可以直接打印Qt的一些内置类型。这样使我们在编码中能够以更加高效和快速。
在 Qt Creator 中使用 qDebug() 打印中文字符时,如果编译器报错,可能有以下几个原因:
1.编码问题:确保源文件的编码格式正确。通常情况下,Qt Creator 默认使用 UTF-8 编码。如果源文件的编码格式不正确,可能会导致中文字符无法正确识别,从而引发编译器报错。
2.头文件包含:确保头文件中包含了正确的编码声明。在源文件的开头,可以添加类似于 #pragma execution_character_set("utf-8") 的声明,以确保编译器正确地处理中文字符。
3.Qt 版本问题:某些旧版本的 Qt 可能对中文字符的处理存在问题。确保您使用的是较新的 Qt 版本,以获得更好的中文字符支持。
4.编译器设置:有时,编译器的设置可能会影响对中文字符的处理。确保编译器的语言环境设置正确,并且支持 UTF-8 编码。
5.字符串转换:如果在 qDebug() 中直接输出中文字符串而没有进行适当的转换,可能会导致编译器报错。您可以尝试将中文字符串转换为 UTF-8 格式,然后再输出。
6.使用转义字符:在某些情况下,直接在代码中使用中文字符可能会导致编译器报错。您可以尝试使用 Unicode 转义字符来表示中文字符,例如 \u4E2D\u6587 表示中文字符 "中文"。
可能是编译器的原因,此处并未找到具体原因,不过可以使用英文打印,在编码中我们尽量多使用英文作为打印主流。
8.Qt坐标系的认识
对于坐标系,我们已经十分熟悉了,但在计算中的坐标系和数学中的坐标系略有不同。
9.信号和槽
在Qt中我们将用户的操作抽象为信号,而槽则是我们处理这种信号的逻辑。讲起信号与槽我们就不得不提到连接他们的一个函数connect
9.1 connect
接下来,我们创建一个按钮,将其连接一个点击信号触发,自定义一个槽来打印一些文字。
9.2 自定义槽函数
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->setupUi(this);
//生成一个button,指定它的父元素this,也就是Widget
QPushButton* button = new QPushButton(this);
button->setText("按钮");
connect(button, &QPushButton::clicked, this, &Widget::HandleCilck);
}
Widget::~Widget()
{
delete ui;
}
//定义槽函数
void Widget::HandleCilck()
{
qDebug() << "Button press";
}
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();
//槽函数声明,在QT5以上版本可不写slots,但为区分还是可以将其写上
public slots:
void HandleCilck();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
9.3 自定义信号
我们将上面的代码进行修改,让它每次点击发送一个信号,通过关联这个信号去打印一段文字。
#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();
//槽函数声明,在QT5以上版本可不写slots,但为区分还是可以将其写上
public slots:
void HandleCilck();
void HandleCreateSign();
//signals:声明信号的关键字
signals:
//我们只需要声明信号,Qt会自动生成信号的定义,并不需要我们定义
void CreateSign();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->setupUi(this);
//生成一个button,指定它的父元素this,也就是Widget
QPushButton* button = new QPushButton(this);
button->setText("按钮");
connect(button, &QPushButton::clicked, this, &Widget::HandleCilck);
connect(this, &Widget::CreateSign, this, &Widget::HandleCreateSign);
}
Widget::~Widget()
{
delete ui;
}
//定义槽函数
void Widget::HandleCilck()
{
// qDebug() << "Button press";
//这次我们不直接打印,我们发送信号,让其接收到我们自定义的信号,再进行打印
emit CreateSign();
}
void Widget::HandleCreateSign()
{
qDebug() << "Custom signals";
}
这里我们就通过按钮点击信号发送我们自定义的信号,接收到我们自定义的信号之后打印一段文字。
注:自定义的信号和槽是可以接收传参的,信号和槽也是可以以多对多的方式进行连接的,同一个信号可以可以被多个槽函数处理,同样的同一个槽可以被多个信号触发。
9.4 断开信号链接(disconnect)
我们创建两个按钮,点击按钮1打印一段文字,点击按钮2断开按钮1信号
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPushButton>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
//槽函数声明,在QT5以上版本可不写slots,但为区分还是可以将其写上
public slots:
void HandleCilck();
void HandleDisCilck();
private:
Ui::Widget *ui;
//为了能让第二个断开槽函数访问到第一个按钮,我们直接将它变为成员函数
QPushButton* button;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//生成一个button,指定它的父元素this,也就是Widget
button = new QPushButton(this);
button->setText("按钮1");
//将Button这个按钮移动到(100,100)这个位置
button->move(100,100);
QPushButton* DisButton = new QPushButton(this);
DisButton->setText("按钮2");
DisButton->move(200,100);
connect(button, &QPushButton::clicked, this, &Widget::HandleCilck);
connect(DisButton, &QPushButton::clicked, this, &Widget::HandleDisCilck);
}
Widget::~Widget()
{
delete ui;
}
void Widget::HandleCilck()
{
qDebug() << "Button press";
}
void Widget::HandleDisCilck()
{
//断开连接
//disconnect的使用方法和connect的使用方式一致
bool link = disconnect(button, &QPushButton::clicked, this, &Widget::HandleCilck);
//断开成功返回true(0),我们可以通过返回值让它重新连接
if(!link)
{
qDebug() << "Button reconnection";
connect(button, &QPushButton::clicked, this, &Widget::HandleCilck);
}
else
{
qDebug() << "Button Disconnected";
}
}
运行后,我们可以通过按钮2l来控制按钮1的连接和断开,加上打印我们更能清楚看到
9.5.lambda表达式
在Qt我们同样可以使用lambda表达式,对一些代码逻辑和处理信号不是那么复杂的信号进行处理。
QPushButton* LambdaButton = new QPushButton(this);
//lambda表达式语法:()[]{处理逻辑}
LambdaButton->setText("Lambda");
connect(LambdaButton, &QPushButton::clicked, this,[](){
qDebug() << "lambda";
});
10.常用控件的介绍以及使用
10.1 QWidget
10.1.1 QWidget的enable属性
enable,setEnable:获取和禁用控件。我们创建一个按钮,通过setEnable禁用它。
QPushButton* LambdaButton = new QPushButton(this);
//lambda表达式语法:()[]{处理逻辑}
LambdaButton->setText("Lambda");
connect(LambdaButton, &QPushButton::clicked, this,[](){
qDebug() << "lambda";
});
//false表示禁用,true启用
LambdaButton->setEnabled(false);
效果如下:
按键变成灰色,无法进行点击。
10.1.2 QWidget的geometry属性
geometry,setGeometry获取和设置控件大小,位置
geometry
属性的结构如下:
x
:窗口部件左上角的 x 坐标。y
:窗口部件左上角的 y 坐标。width
:窗口部件的宽度。height
:窗口部件的高度。
通过设置窗口部件的 geometry
属性,可以将其放置在窗口中的任意位置,并指定其大小。
QPushButton* LambdaButton = new QPushButton(this);
//lambda表达式语法:()[]{处理逻辑}
LambdaButton->setText("Lambda");
connect(LambdaButton, &QPushButton::clicked, this,[](){
qDebug() << "lambda";
});
//false表示禁用,true启用
LambdaButton->setEnabled(false);
//返回值是一个QRect
QRect rect = LambdaButton->geometry();
//设置控件大小
//可以传入一个QRect类型,也可以直接复制
LambdaButton->setGeometry(500, 500, 100, 100);
运行结果如下:
10.1.3 WindowFrame的影响
在Qt中,WindowFrame是一个窗口部件(QWidget)的属性,它控制着窗口部件周围的边框和装饰,设置WindowFrame的值可以影响窗口的外观和行为。
当windowFrame设置为 true 时,窗口部件将显示标准的窗口边框和装饰,包括标题栏,边框和窗口按钮(最大化,最小化,关闭等)。通常用于创建独立的,可移动的窗口的情况。
当windowFrame设置为 false 时,窗口部件将不再显示标准的窗口边框和装饰,而仅显示窗口本身内容,通常用于创建自定义的,非模态的对话框或小部件,以便将嵌入式到其他界面中。
10.1.4 QWidget的windowTitle属性
windowTitle,setWindowTitle获取和设置窗口标题
//设置窗口标题为Window Frame Example
this->setWindowTitle("Window Frame Example");
运行结果:
10.1.5 QWidget的windowlcon属性
windowlcon,setwindowIcon获取设置窗口LOGO
使用这个函数我们需要准备一张图片作为它的LOGO,因为部分情况下用户会将图片删除,导致程序无法正常运行,Qt中引入一个将图片进行二进制编码的过程,将图片加入到代码中,优点是,数据不容易丢失。缺点是,生成的可执行程序会较大,所以不建议将视频也进行编码。
具体操作如下:
//加载图片
QIcon WidgetMoon(":/moon.png");
//设置Widget的LOGO
this->setWindowIcon(WidgetMoon);
运行结果:
给大家推荐一个下载图片的网址:阿里巴巴矢量图
这是一个开源的图库,里面内容相对较为丰富。
10.1.6 QWidget的WindowOpacity属性
WindowOpacity,setWindowOpacity设置透明度,
我们创建两个按钮,分别控制其+透明度和-透明度
QPushButton* AddButton = new QPushButton(this);
QPushButton* MinusButton = new QPushButton(this);
AddButton->setText("+");
AddButton->setGeometry(200, 400, 100,100);
connect(AddButton, &QPushButton::clicked, this, &Widget::HandleWidgetAddLucency);
MinusButton->setText("-");
MinusButton->setGeometry(500, 400, 100,100);
connect(MinusButton, &QPushButton::clicked, this, &Widget::HandleWidgetMinusLucency);
void Widget::HandleWidgetAddLucency()
{
float AddLucency = this->windowOpacity();
//虽然每次设置都有判断,但为了出现意外情况,我们还是有必要
//进行判断的
if(AddLucency < 1)
{
//设置浮点数,按钮每次按下,将其+0.1
//并设置QWidget的透明度
AddLucency += 0.1;
this->setWindowOpacity(AddLucency);
}
}
void Widget::HandleWidgetMinusLucency()
{
float MinusLucency = this->windowOpacity();
if(MinusLucency > 0)
{
//设置浮点数,按钮每次按下,将其-0.1
//并设置QWidget的透明度
MinusLucency -= 0.1;
this->setWindowOpacity(MinusLucency);
}
}
效果如下:
10.1.7 QWidget的cursor属性
cursor,setCursor获取设置控件鼠标样式
通过Qt Designer我们可以看到其内置的鼠标样式,我们也可以通过鼠标点到我们想要查看的函数(如cursor)按F1,通过查看文档去了解其鼠标样式。
当然我们也可以自定义鼠标样式,首先加载图片,步骤已经说过,就不再赘述。如若不会可跳转至"10.1.5 QWidget的windowlcon属性"查看具体操作步骤。
选择已经下载好的文件,进行添加
//此处不能用QIcon加载光标图片,类型不匹配
// QIcon CursorBasketball(":/basketball.png");
//只能使用QPixmap
QPixmap CursorBasketball(":/basketball.png");
QCursor cursor(CursorBasketball);
this->setCursor(cursor);
如果只是这样设置,你会发现光标的大小以及热点(hotspot)并不是很理想
注:此处热点,并非我们手机打开的热点,而是光标点击生效的位置
//此处不能用QIcon加载光标图片,类型不匹配
// QIcon CursorBasketball(":/basketball.png");
//只能使用QPixmap
QPixmap CursorBasketball(":/basketball.png");
//设置图片大小
CursorBasketball = CursorBasketball.scaled(100,100);
QCursor cursor(CursorBasketball);
//还原默认光标
//QApplication::restoreOverrideCursor();
this->setCursor(cursor);
10.1.8 QWidget的font属性
font,setFont获取和设置字体属性(包括字体,字号,加粗,切斜等)
在Qt Designer中我们可以清楚的看到
当我们通过Qt Designer中创建一个Label将它的字体大小等信息全部设置后,我们将看到
那我们用代码的方式实现,创建两个Label,一个不设置字体,一个同上设置为这种字体,运行代码我们来看结果。
//创建两个QLabel控件
QLabel* Setlabel = new QLabel(this);
QLabel* NoSettingsLabel = new QLabel(this);
//设置位置大小等信息
Setlabel->setGeometry(200,200, 400,100);
Setlabel->setText("This is unset text");
NoSettingsLabel->setGeometry(550,200,100,100);
NoSettingsLabel->setText("This is the text after setting");
//创建字体类型
QFont font;
font.setFamily("黑体");//设置字体家族
font.setPointSize(20);//设置字号
font.setBold(true);//设置粗体
font.setItalic(true);//设置斜体
font.setStyleStrategy(QFont::PreferAntialias); // 启用字体的锯齿线渲染策略
font.setStrikeOut(true);//设置删除线
Setlabel->setFont(font);//将配置到的信息加载进入
运行程序,我们将得到
10.1.9 QWidget的toolTip属性
toolTip,setToolTip获取设置控件的工具提示文本,当鼠标悬停置控件上一段时间会显示简短说明。比如:此处的橡皮擦。我们创建一个橡皮擦设置悬停后出现一段提示语。
QLabel* EraserLabel = new QLabel(this);
QPixmap pixmap(":/eraser.png");//加载图片
EraserLabel->setPixmap(pixmap.scaled(40, 40));//设置图片以及图片大小
EraserLabel->setGeometry(100,100,40,40);//设置部件位置,大小
EraserLabel->setToolTip("This is an eraser");//设置鼠标悬停后的提示语
QString tooltipText = EraserLabel->toolTip();//获取当前的提示文本
qDebug() << tooltipText;
10.1.10 QWidget的focusPolicy属性
focusPolicy,setFocusPolicy获取设置焦点(用户界面中当前接收键盘输入的控件或部件)
在Qt Designer中有以下几种可供选择
在代码中可选值:
Qt::FocusPolicy枚举类型定义了focusPolicy属性的可选值:
* Qt::NOFocus(0):控件永远不会接受焦点。
* Qt::TabFocus(1):控件永远只会接受Tab键的焦点。
* Qt::ClickFocus(2):控件永远只会接受鼠标点击的焦点。
* Qt::StrongFocus(3):控件接受鼠标点击和Tab键的焦点
* Qt::WheelFocus:控件接受鼠标滚轮滑动的焦点。
注:默认情况下,大多数QWidget子类的focusPolicy属性都为NoFocus并不会接受焦点。
在Qt Designer中以下两种控件创建后,会接受焦点
其中Line Edit是单行输入,Text Edit和Plain Text Edit是多行输入.
创建三个Line Edit控件,分别将他们的属性设置为NOFocus,TabFocus和ClickFocus。
QLineEdit* NoFocusEdit = new QLineEdit(this);
QLineEdit* TabFocusEdit = new QLineEdit(this);
QLineEdit* ClickFocusEdit = new QLineEdit(this);
NoFocusEdit->setGeometry(100,100,200,40);
TabFocusEdit->setGeometry(100,200,200,40);
ClickFocusEdit->setGeometry(100,300,200,40);
NoFocusEdit->setFocusPolicy(Qt::NoFocus);//无法获取焦点
TabFocusEdit->setFocusPolicy(Qt::TabFocus);//鼠标无法无法获取焦点
ClickFocusEdit->setFocusPolicy(Qt::ClickFocus);//Tab键无法获取焦点
运行结果:
10.1.11 QWidget的styleSheet属性
styleSheet,setStyleSheet获取设置控件样式和外观(允许使用CSS-like语法来设置和定制控件样式和外观,类似与Web开发中的CSS样式表,可以影响部件的背景,边框,字体和颜色等视觉方面的表现)
语法格式
widget->setStyleSheet("property: value; property2: value2; ...");
其中,property
是样式属性,value
是对应的属性值。多个属性之间用分号分隔。
创建一个Label设置它的styleSheet属性
QLabel* StleSheetLabel = new QLabel(this);
StleSheetLabel->setText("这是被设置后的Label");
QRect rect = this->geometry();
StleSheetLabel->setGeometry(rect.width() / 2, rect.height() / 2, 200, 100);
//设置背景颜色为蓝色,rgba是三原色:rgba(red, green, blue, alpha)
//其中alpha代表透明度0表示完全透明,1表示完全不透明
//字体大小为16个像素
//边框样式为2像素的红色表框
StleSheetLabel->setStyleSheet("background-color: rgba(00, 197, 209, 1); font-size: 16px; border: 2px solid red;");
运行结果
样式表可以通过选择器来选择特定的控件。如果我们只想给一个特定的控件设置样式,可以使用类选择器和ID选择器
QPushButton#myButton {
background-color: blue;
color: white;
}
#myButton
是按钮的ID选择器,表示样式适用于具有 myButton
ID 的按钮。
属性设置: 样式表支持许多常见的CSS属性,例如:
还可以根据具体的QWidget类型和需求设置更多特定的样式属性。
background-color:
设置元素的背景颜色
color:设置文本内容颜色
font-size:设置问题字体大小
border:设置元素边框样式
padding:设置元素边框与内容之间的空白区域
等等...
10.2 Button按键
10.2.1 QPushButton添加图标
使用图像文件作为图标(准备好图片,加载给按钮上即可)
// 创建一个 QPushButton
QPushButton *button = new QPushButton(this);
button->setGeometry(100, 100, 100, 100);
// 加载图标
QIcon icon(":/Button.png");
// 缩放图标
QSize iconSize(100,100);
// 设置按钮的图标
button->setIcon(icon);
// 更新图片大小
button->setIconSize(iconSize);
运行结果
使用Qt中的Qt Designer拖放方式进行添加图标
运行后
10.2.2 QPushButton添加快捷
在Qt中按键也是可以使用快捷键按下的(QShortcut)
创建五个按键,其中四个按键分别控制上下左右,移动非上下左右的按键。
接下来,我们将他们绑定槽函数,以及添加快捷键。
connect(ui->pushButton_down, &QPushButton::clicked, this, &Widget::HandleDownCilck);
connect(ui->pushButton_up, &QPushButton::clicked, this, &Widget::HandleUpCilck);
connect(ui->pushButton_left, &QPushButton::clicked, this, &Widget::HandleLeftCilck);
connect(ui->pushButton_right, &QPushButton::clicked, this, &Widget::HandleRightCilck);
// 直接通过按键的名字来设置. 虽然简单, 但是容易写错.
// ui->pushButton_up->setShortcut(QKeySequence("ctrl + w"));
// ui->pushButton_down->setShortcut(QKeySequence("s"));
// ui->pushButton_left->setShortcut(QKeySequence("a"));
// ui->pushButton_right->setShortcut(QKeySequence("d"));
// 还可以通过按键的枚举来设置按键快捷键.
// ui->pushButton_up->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_W));
ui->pushButton_up->setShortcut(QKeySequence(Qt::Key_W));
ui->pushButton_down->setShortcut(QKeySequence(Qt::Key_S));
ui->pushButton_left->setShortcut(QKeySequence(Qt::Key_A));
ui->pushButton_right->setShortcut(QKeySequence(Qt::Key_D));
// 开启鼠标点击的连发功能(键盘的连发默认就是支持的)
ui->pushButton_up->setAutoRepeat(true);
ui->pushButton_down->setAutoRepeat(true);
ui->pushButton_left->setAutoRepeat(true);
ui->pushButton_right->setAutoRepeat(true);
void Widget::HandleUpCilck()
{
QRect rect = ui->pushButton->geometry();
ui->pushButton->setGeometry(rect.x(), rect.y() - 5, rect.width(), rect.height());
}
void Widget::HandleLeftCilck()
{
QRect rect = ui->pushButton->geometry();
ui->pushButton->setGeometry(rect.x() - 5, rect.y(), rect.width(), rect.height());
}
void Widget::HandleRightCilck()
{
QRect rect = ui->pushButton->geometry();
ui->pushButton->setGeometry(rect.x() + 5, rect.y(), rect.width(), rect.height());
}
void Widget::HandleDownCilck()
{
QRect rect = ui->pushButton->geometry();
ui->pushButton->setGeometry(rect.x(), rect.y() + 5, rect.width(), rect.height());
}
运行结果
此时我们的天猫汽车就可以动起来啦~
10.2.3 QRadioButton的使用
QRadioButton是Qt框架中用于创建单选按钮的类(当存在多个QRadioButton时,会出现互斥现象,也就是只能选择一个,如果我们想要多选,只能将他们做分组处理)
我们创建一个关于性别的按钮选项。
Gender = new QLabel(this);
Gender->setText("请选择你的性别:");
Gender->setGeometry(200,180, 200 ,20);
//创建两个QRadioButton按钮
ManRadioButton = new QRadioButton(this);
WomanRadioButton = new QRadioButton(this);
ManRadioButton->move(200,200);
WomanRadioButton->move(200,230);
ManRadioButton->setText("man");
WomanRadioButton->setText("woman");
connect(ManRadioButton, &QRadioButton::clicked, this, &Widget::HandleManRadioButtonClick);
connect(WomanRadioButton, &QRadioButton::clicked, this, &Widget::HandleWomanRadioButtonClick);
void Widget::HandleManRadioButtonClick()
{
Gender->setText("您选择的性别为man");
}
void Widget::HandleWomanRadioButtonClick()
{
Gender->setText("您选择的性别为woman");
}
运行后:
在此按键中,我们还可以通过setChecked来设置默认选项
//设置默认选项
ManRadioButton->setChecked(true);
Gender->setText("请选择你的性别:man");
完成后我们再次运行程序就会直接得到
并不需要点击触发。
当然在QRadioButton控件也有四种信号(clicked,pressed,released,toggled)
clicked:点击单选按钮时发出的信号
pressed:用户按下单选按钮时发出的信号
released:用户释放单选按钮时发出的信号
toggled:单选按钮的选中状态切换时发出的信号
如果我们想在同一个界面按下多个QRadioButton控件,就必须将他们进行分组(QButtonGroup)
// 使用 QButtonGroup 对单选按钮进行分组
QButtonGroup* group1 = new QButtonGroup(this);
QButtonGroup* group2 = new QButtonGroup(this);
QButtonGroup* group3 = new QButtonGroup(this);
// 把上述单选按钮, 放到不同的组里.
group1->addButton(ui->radioButton);
group1->addButton(ui->radioButton_2);
group1->addButton(ui->radioButton_3);
group2->addButton(ui->radioButton_4);
group2->addButton(ui->radioButton_5);
group2->addButton(ui->radioButton_6);
group3->addButton(ui->radioButton_7);
group3->addButton(ui->radioButton_8);
group3->addButton(ui->radioButton_9);
运行后
10.2.4 QCheckBox的使用
Qt 框架中用于创建复选框(checkbox)的类。复选框允许用户从多个选项中选择一个或多个。
使用方法基本同QRadioButton类似
QVBoxLayout layout(this);
// 创建多个复选框
QCheckBox *checkBox1 = new QCheckBox("Option 1");
QCheckBox *checkBox2 = new QCheckBox("Option 2");
checkBox1->move(100,100);
checkBox2->move(100, 150);
// 添加复选框到布局中
layout.addWidget(checkBox1);
layout.addWidget(checkBox2);
// 设置默认选中状态
checkBox1->setChecked(true);
// 连接信号和槽,处理选中状态变化
QObject::connect(checkBox1, &QCheckBox::stateChanged, [&](int state) {
if (state == Qt::Checked) {
qDebug() << "Option 1 checked";
} else {
qDebug() << "Option 1 unchecked";
}
});
QObject::connect(checkBox2, &QCheckBox::stateChanged, [&](int state) {
if (state == Qt::Checked) {
qDebug() << "Option 2 checked";
} else {
qDebug() << "Option 2 unchecked";
}
});
运行结果:
10.3 QLabel
10.3.1 QLanel文本显示方式
在Lanel控件中还提供了文本显示方式(纯文本,富文本,markdown文本)
具体他们有什么区别呢
我们使用Qt Designer创建三个Label控件,分别设置他们的文本
// 把第一个 label 设置成显示纯文本.
ui->label->setTextFormat(Qt::PlainText);
ui->label->setText("# 这是一段纯文本");
//把第二个 label 设置成显示富文本.
ui->label_2->setTextFormat(Qt::RichText);
ui->label_2->setText("<b>这是一段富文本</b>");
//把第三个 label 设置成markdown文本.
ui->label_2->setTextFormat(Qt::MarkdownText);
ui->label_3->setText("# 这是一段markdown文本");
我们跳转到文本设置的枚举类型中,
PlainText:纯文本,标签默认支持这种格式。
RichText :富文本格式,Label
不支持此格式,但可以使用 RichTextBox
控件来显示富文本。
AutoText:自动检测文本格式并相应地显示。这需要自定义逻辑来识别文本格式并选择合适的控件进行显示。
MarkdownText :Markdown 格式,Label
不支持,但可以使用第三方库将 Markdown 转换为 HTML,然后使用 WebBrowser
控件显示。
10.3.2 QLanel设置图片
接下来,我们通过在Qt Designer中创建一个Label对象,然后加载一张图片,进行填充整个QWidget
//获取widget窗口的坐标以及大小
QRect rect = this->geometry();
//将Label控件设置成窗口大小
ui->label->setGeometry(0, 0, rect.width(), rect.height());
QPixmap pixmap(":/image/angry-2.png");
ui->label->setPixmap(pixmap);
// 启动自动拉伸. 此时图片就能够填充满整个窗口了.
ui->label->setScaledContents(true);
运行结果:
但是,当我们拉伸窗口是,图片并不会随着我们的拉伸而变化,此时我们就会触发resize事件,像resize这样的事件是连续变化的。如果我们想是图片随着我们的拉伸而变化时,我们就可以通过重写widget(父类)的resizeEvent(虚函数)来改变Label大小
void resizeEvent(QResizeEvent *event);//声明一下resizeEvent
void Widget::resizeEvent(QResizeEvent *event)
{
//此处的形参 event 是非常有用的, 这里就包含了触发这个 resize 事件这一时刻, 窗口的尺寸的数值.
//我们可以通过打印来看event的变化
qDebug() << event->size();
}
通过不断地拉伸就可以获得widget的长宽
那么我们想设置它的拉伸而改变Label的大小就十分简单了
void Widget::resizeEvent(QResizeEvent *event)
{
//此处的形参 event 是非常有用的, 这里就包含了触发这个 resize 事件这一时刻, 窗口的尺寸的数值.
//我们可以通过打印来看event的变化
qDebug() << event->size();
ui->label->setGeometry(0,0,event->size().width(), event->size().height());
}
运行结果:
10.3.3 QLabel设置自动换行,边距,缩进
通过这样的设置我们能够更加清楚的,看到Label控件。
创建四个Label控件,分别设置他们的对齐方式,自动换行,缩进,边距
// 在构造函数中, 给这几个 label 设置不同的属性.
// 设置对齐方式
ui->label->setText("这是一段文本");
ui->label->setAlignment(Qt::AlignRight | Qt::AlignTop);
// 设置自动换行
ui->label_2->setText("这是一段很长的文本这是一段很长的文本这是一段很长的文本");
ui->label_2->setWordWrap(true);
// 设置缩进(需要注意的是,缩进是全部缩进)
ui->label_3->setText("这是一段很长的文本这是一段很长的文本这是一段很长的文本");
ui->label_3->setWordWrap(true);
ui->label_3->setIndent(50);
// 设置边距
ui->label_4->setText("这是一段很长的文本这是一段很长的文本这是一段很长的文本");
ui->label_4->setWordWrap(true);
ui->label_4->setMargin(50);
运行结果
在设置对齐方式中提供了很多种,我们可以进入它的枚举中进一步了解
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
};
下面是对每个枚举值的解释:
-
AlignLeft
和AlignLeading
:左对齐 -
AlignRight
和AlignTrailing
:右对齐 -
AlignHCenter
:水平居中对齐 -
AlignJustify
:两端对齐 -
AlignAbsolute
:绝对对齐 -
AlignHorizontal_Mask
:水平对齐掩码,用于表示所有水平对齐方式的组合 -
AlignTop
:顶部对齐 -
AlignBottom
:底部对齐 -
AlignVCenter
:垂直居中对齐 -
AlignBaseline
:基线对齐(该值与 Qt::TextSingleLine = 0x100 可能冲突,但由于AlignBaseline
只用于布局中,不会传递给QPainter::drawText()
,因此不会产生歧义) -
AlignVertical_Mask
:垂直对齐掩码,用于表示所有垂直对齐方式的组合 -
AlignCenter
:居中对齐,既包括垂直居中对齐又包括水平居中对齐
这些枚举值可以组合使用,以实现所需的对齐方式。例如,AlignLeft | AlignTop
表示左上对齐,AlignHCenter | AlignVCenter
表示水平和垂直居中对齐。
10.3.4 QLabel设置伙伴
Qt中QLabel中写的文本,是可以指定为"快捷键"(比之QPushButton逊色很多)
在文本中使用 & + 字符的形式来表示快捷键
比如&A => 通过键盘alt + a出发次快捷键
通过绑定伙伴关系就可以听过快捷按钮选中对应的单选按钮/复选按钮了!
// 设置 label 和 radioButton 伙伴关系
ui->label->setBuddy(ui->radioButton);
ui->label_2->setBuddy(ui->radioButton_2);
运行结果:
10.4 QLCDNumber
QLEDNumber控件是一种显示数字的控件,类似与"老式计算器"
*intValue: QLEDNumber显示的数值(int)
*value: QLCDNumber 显示的数字值(double)和 intValue 是联动的.
例如给 value 设为 1.5,intValue 的值就是 2.
另外,设置 value和intValue的方法名字为display ,而不是 setValue 或者setIntValue
*digitCount: 显示几位数字
*mode: 数字显示形式!
QLCDNumber::Dec:十进制模式,显示常规的十进制数字。
QLCDNumber::Hex:十六进制模式,以十六进制格式显示数字。
QLcDNumber::Bin:二进制模式,以二进制格式显示数字
QLcDNumber::oct :八进制模式,以八进制格式显示数字。
注:只有十进制的时候才能显示小数点后的内容
*segmentStyle: 设置显示风格。
QLCDNumber::Flat:平面的显示风格,数字呈现在一个平坦的表面上。
QLCDNumber::0utline:轮廓显示风格,数字具有清晰的轮廓和阴影效果。
QLCDNumber::Filled:填充显示风格,数字被填充颜色并与背景区分开。
*smallDecimalPoint:设置比较小的 .小数点
创建一个QLCD Number,让它显示从10到0.
//设置初始值10
ui->lcdNumber->display(10);
//想要实现计时功能,在Qt中提供了一个QTime的计时器
Timer = new QTimer(this);
// 把 QTimer 的 timeout 信号和咱们自己的槽函数进行连接
connect(Timer, &QTimer::timeout, this, &Widget::handleTimer);
// 启动定时器, 参数是触发 timeout 的周期. 单位是 ms
Timer->start(1000);
void Widget::handleTimer()
{
// 先拿到 LCDNumber 中的数字
int value = ui->lcdNumber->intValue();
if (value <= 0) {
// 数字减到 0 了, 停止定时器.
timer->stop();
return;
}
ui->lcdNumber->display(value - 1);
}
运行结果:
如果我们不使用Qt内置的计时器的话,我们能不能自己写一个计时器呢,不妨试一下
int value = 10;
ui->lcdNumber->display(value);
while (true) {
// 先休眠 1s
std::this_thread::sleep_for(std::chrono::seconds(1));
if (value <= 0) {
break;
}
value -= 1;
ui->lcdNumber->display(value);
}
当我们写出这样一段函数,运行之后,我们的程序会在十秒后显示出来
还记得我们之前说过的吗,我们在构造函数执行结束后才会进行显示。
那我们能不能写一个线程,使用多线程去实现这么一个操作呢
std::thread t([this] () {
int value = this->ui->lcdNumber->intValue();
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
if (value <= 0) {
break;
}
value -= 1;
ui->lcdNumber->display(value);
}
});
运行这段代码后,不仅不会显示,还会出现一个:
这是因为在Qt里,界面只能有主线程(main所在的线程)进行维护更新。
对于GUI来说,内部包含了很多的状态,Qt为保证修改界面的过程中,线程安全不会受到影响,所以禁止了其他线程的修改。
对于Qt来说,槽函数默认情况下是由主函数调用的,在槽函数中修改界面是没有任何问题的。
10.5 ProgressBar
*minimum:进度条最小值
*maximum:进度条最大值
*value:进度条当前值
*alignment:文本中进度条的对其方式
Qt::AlignLeft: 左对齐
Qt::AlignRight:右对齐
Qt::AlignCenter:中间对齐
Qt::AlignJustify:两端对齐
*textVisble:进度条数字是否可见
*orientation:进度条的方向是水平还是垂直
*invertAppearance:是否为朝反向增长的进度
*textDirection:文本朝向
*format:展示的数字格式。
%p:表示进度的百分比(0-100)
%v:表示进度的数值(0-100)
%m:剩余时间(毫秒)
%t:总时间(毫秒)
实现进度条岁时间增长(每个100毫秒+1)
//设置value的值
ui->progressBar->setValue(0);
//创建QTimer实例并绑定
Timer = new QTimer(this);
connect(Timer, &QTimer::timeout, this, &Widget::handleTimer);
//启动Timer计时
Timer->start(100);
void Widget::handleTimer()
{
//获取progressBar的值
int value = ui->progressBar->value();
if(value >= 100)
{
Timer->stop();
return;
}
ui->progressBar->setValue(value + 1);
}
运行结果
不知道大家有没有这样玩过,我们只在.cpp中包含QTimer头文件,而没有在.h中包含,程序却依然可以运行,这是为什么呢。
这个是c++的特殊技巧,在编译横向对比中,C/C++语言的编译时间要比其他语言编译时间更久,经过一些大佬们的研究发现是因为#include包含头文件,文本替换所导致的,为了能够优化这一编译时长的问题。在C++中就提供了一个专门包含所有类的"前置声明"头文件。在Qt中同样也适用,
这样虽然减少了一定的损耗,但是在一些大型项目中,并不会因为只使用它做声明而不包含它的头文件,所以并不能很好的解决这些问题,有些大厂中就会从硬件下手。当然在c++20中引入了module(模版)这个概念,但对于#include依然使用。
10.6 QCalendarWidget
*selectDate:当前选中的日期
*minimumDate:最小日期
*maximumDate:最大日期
*firstDayOfWeek:每周的第一天(也就是日历的第一列) 是周几
*gridVisible:是否显示表格的边框
*selectionMode:是否允许选择日期
*navigationBarVisible:日历上方标题是否显示
*horizontalHeaderFormat:日历上方标题显示的日期格式
*verticalHeaderFormat:日历第一列显示的内容格式
*dateEditEnabled:是否允许日期被编辑
QCalendarWidget信号
selectionChanged(const QDate&):当选中的日期发生改变时发出
activated(const QDate&):当双击一个有效的日期或者按下回车键时发出,形参是一个QDate类型,保存了选中的日期
currentPageChanged(int,int):当年份月份改变时发出,形参表示改变后的新年份和月份
界面中创建一个QCalendarWidget和QLabel,当我们点击QCalendarWidget上的时间时,QLabel也随之发生改变
在Qt Designer中创建QCalendarWidget和QLabel两个控件,然后在QCalendarWidget赚到槽
我们可以打印一下看他的值
void Widget::on_calendarWidget_selectionChanged()
{
QDate date = ui->calendarWidget->selectedDate();
qDebug() << date;
}
void Widget::on_calendarWidget_selectionChanged()
{
QDate date = ui->calendarWidget->selectedDate();
// qDebug() << date;
//将date转为string
ui->label->setText(date.toString());
}
运行结果:
10.7 QLineEdit
10.7.1 QLineEdit的使用
*text:输入框中的文本
*inputMask:输入内容格式约束
*maxLength:最大长度
*frame:是否添加边框
*echonMode:显示方式
QLineEdit::Normal:这是默认值,文本框会显示输入的文本。
QLineEdit::Password:这种情况下,输入的字符会被隐藏,通常用星号(*)或等号(=)代替。
QLineEdit::NoEcho:在这种模式下,文本框不会显示任何输入的字符。
*cursorPosition:光标所在位置
*alignment:文字对齐方式,设置水平和垂直方向的对齐
*dragEnabled:是否允许拖拽
*readOnly:是否是只读(不允许修改)
*placeHolderText:当输入框内容为空的时候,显示什么样的提示信息
*clearButtonEnabled:是否会自动显示出"清除按钮"
核心信号
*void cursorPositionChanged(int old, int new):当鼠标移动时发出此信号,old为先前的位置,new为新的位置
*void editingFinished():当按返回或者回车键时,或者行编辑失去焦点时,发出此信号
*void returnPressed():当返回或回车键按下时发出此信号
如果设置了验证器,必须要验证通过,才能触发
*void selectionChanged():当选中的文本改变时,发出此信号
*void textChanged(const QString &text):当QLineEdit中的文本改变时,发出此信号,text是新的文本,代码对新文本的修改能够触发这个信号
*void textEdited(const QString &text):当QLineEdit中的文本改变时,发出此信号,text是新的文本。代码对文本的修改不能触发此信号
实现,当用户点击提交时,获取注册内容并打印
//初始化第一个框提示文本"请输入您的电话号码"
ui->lineEdit_phone->setPlaceholderText(QString("Please enter your telephone number"));
ui->lineEdit_phone->setClearButtonEnabled(true);
//手机号码具有固定格式,此处的"0"代表数字
ui->lineEdit_phone->setInputMask("000-0000-0000");
//初始第二框文本"请输入账户"
ui->lineEdit_account->setPlaceholderText(QString("Please enter account"));
ui->lineEdit_account->setClearButtonEnabled(true);
//第三,四框输入文本"请输入密码"和"请确认密码"
ui->lineEdit_password->setPlaceholderText(QString("enter your PIN"));
ui->lineEdit_affirm_password->setPlaceholderText(QString("Please confirm password"));
//密码不希望被其他人知晓所以显示设置为密码模式
ui->lineEdit_password->setEchoMode(QLineEdit::Password);
ui->lineEdit_affirm_password->setEchoMode(QLineEdit::Password);
ui->lineEdit_phone->setClearButtonEnabled(true);
ui->lineEdit_affirm_password->setClearButtonEnabled(true);
void Widget::on_pushButton_clicked()
{
qDebug() <<"号码"<<ui->lineEdit_phone->text()
<<"账户"<<ui->lineEdit_account->text()
<<"密码"<<ui->lineEdit_password->text()
<<"确认密码"<<ui->lineEdit_affirm_password->text();
}
运行结果
很明显就算我们两次输入的密码,不相同依旧可以提交,这样显然是不合法的。
//默认禁止点击提交
ui->pushButton->setEnabled(false);
void Widget::Compare()
{
const QString& s1 = ui->lineEdit_password->text();
const QString& s2 = ui->lineEdit_affirm_password->text();
ui->pushButton->setEnabled(false);
if (s1.isEmpty() && s2.isEmpty()) {
ui->label->setText("Password is empty");
//如果两次输入的密码相等,且所有QLineEdit控件不为空就将"提交"设置为可用
} else if (s1 == s2 && !(ui->lineEdit_account->text().isEmpty()) && !(ui->lineEdit_phone->text().isEmpty())) {
ui->label->setText("The passwords are the same");
ui->pushButton->setEnabled(true);
} else {
ui->label->setText("The password is not the same");
}
}
void Widget::on_lineEdit_password_textEdited(const QString &arg1)
{
//防止报警告
(void)arg1;
Compare();
}
void Widget::on_lineEdit_affirm_password_textEdited(const QString &arg1)
{
//防止报警告
(void)arg1;
Compare();
}
我们还提供了显示按钮,当它按下就显示其密码内容
void Widget::on_radioButton_toggled(bool checked)
{
if (checked) {
// true 则是 "显示密码" 状态, 就把输入框的显示模式, 设为 Normal
ui->lineEdit_password->setEchoMode(QLineEdit::Normal);
ui->lineEdit_affirm_password->setEchoMode(QLineEdit::Normal);
} else {
// false 则是 "隐藏密码" 状态, 就把输入框的显示模式, 设为 Password
ui->lineEdit_password->setEchoMode(QLineEdit::Password);
ui->lineEdit_affirm_password->setEchoMode(QLineEdit::Password);
}
}
在我们刚才提供的判断号码是否合法的情况的其实是不太完整的,因为inputMask功能比较有限,只能进行简单的验证。为了更好的判断用户所输入内容的合法化,大佬们研究出了"正则表达式"
正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
概念:正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑。
正则表达式的作用:
1.验证数据的有效性
2.替换文本内容
3.从字符串中提取子字符串
//手机号码具有固定格式,此处的"0"代表数字
// ui->lineEdit_phone->setInputMask("000-0000-0000");
// 就需要给单行输入框设置验证器. 基于正则表达式来完成验证的~~
QRegExp regExp("^1\\d{10}$");
ui->lineEdit_phone->setValidator(new QRegExpValidator(regExp));
"^1\\d{10}$"这是一个简单的正则表达式,这里我们只是生成了一个验证器,验证器怎么使用,还需要我们自己定义
void Widget::on_lineEdit_phone_textEdited(const QString &arg1)
{
QString text = arg1;
int pos = 0;
if(ui->lineEdit_phone->validator()->validate(text, pos) == QValidator::Acceptable)
{
ui->pushButton->setEnabled(true);
}
else{
ui->pushButton->setEnabled(false);
}
}
1.Invalid:表示状态或结果为无效或不可接受。
2.Intermediate:表示状态或结果为中间状态,可能需要进一步处理或者待定。
3.Acceptable:表示状态或结果为可接受或有效。
10.7.2 QLineEdit属性
QTextEdit 是 Qt 框架中用于显示和编辑文本的控件,它具有许多可设置和调整的属性。以下是一些常用的 QTextEdit 属性:
1.文本内容相关属性:
*text:获取或设置编辑框中的文本内容。
*plainText:获取或设置编辑框中的纯文本内容。
*html:获取或设置编辑框中的 HTML 格式文本内容。
2.显示和布局相关属性:
*lineWrapMode:设置文本自动换行的模式。
*lineWrapColumnOrWidth:设置文本换行的宽度或列数。
*tabStopWidth:设置文本编辑框中 Tab 键的停止位宽度。
*wordWrapMode:设置单词自动换行的模式。
3.字体和样式相关属性:
*font:设置或获取文本编辑框中的字体。
*alignment:设置文本的对齐方式(左对齐、右对齐、居中等)。
*textColor:设置文本的颜色。
4.滚动和视图控制属性:
*verticalScrollBarPolicy:设置垂直滚动条的显示策略。
*horizontalScrollBarPolicy:设置水平滚动条的显示策略。
5.输入相关属性:
*readOnly:设置文本编辑框是否只读。
*acceptRichText:设置是否接受富文本格式。
*autoFormatting:设置自动格式化选项(如自动链接检测等)。
6.选择和光标相关属性:
*cursorWidth:设置光标的宽度。
*cursorFlashTime:设置光标闪烁的时间间隔。
*textInteractionFlags:设置文本的交互标志(包括可编辑、可选择等)。
7.撤销和重做相关属性:
*undoRedoEnabled:设置是否启用撤销和重做功能。
8.文本变化和内容选择信号:
*extChanged:文本内容改变时的信号。
*selectionChanged:选择内容改变时的信号。
本篇文章暂时先写到这里,后续会出一篇进阶,我将介绍其他常用控件,以及在Qt中线程和网络相关的问题。