QT_快速入门

QT_快速入门

01QT简介及环境搭建

⼀、QT简介

1.1 QT特点

● Qt是⼀种 C++ 的开发类库( 不是⼀种编程语⾔),主要⽤来开发图形⽤户界

⾯,也可⽤于开发⾮GUI程序。

● Qt 是⼀个跨平台的基于 C++ 的⼀个程序开发框架(与MFC不同),可以搭建

在不同的操作平台:Windows,Linux, Mac, 嵌⼊式平台(ARM);

● Qt 的基础开发语⾔是 C++,但是Qt 有⾃⼰核⼼特点:在C++基础上提出了⾃

⼰的扩展,新特征:

1) 信号与槽;

2) 元对象系统:(预处理)

● Qt 还存在 Python、Ruby、Perl 等脚本语⾔的绑定, 也就是说可以使⽤这些

脚本语⾔开发基于 Qt 的程序。

● Qt 主要⽤于桌⾯程序开发和嵌⼊式开发,⽤QT开发的经典案例如Ubuntu的桌

⾯,WPS office, google earth,…;

相⽐其他GUI库的优点:

1.跨平台

在linux/unix中,qt的底层调⽤GTK,底层调⽤的接⼝都是win32 API的接⼝.

  1. Qt提供了⼤量的模块,在模块内提供⼗分常⽤的类,类中⼜提供了很多的⽅

法,可以缩短开发周期;

  1. Qt 的信号与槽机制提供了⾮常⽅便的类中通讯。

1.2 其他GUI开发⼯具简介

Linux 下常⽤的 GUI 库有基于 C++ 的 Qt、GTK+、wxWidgets,以及基于 Java 的 AWT 和 Swing,其中最著名的就是 Qt 和 GTK+。

windows下开发GUI的主要有:

基于C++的QT、wxWidgets,MFC;

基于 C# 的有 WinForm、WPF,

基于Go语⾔的有 walk 和 electron;

基于PYTHON语⾔的有 PYQT 和wxWidgets ;

MFC是什么: 
微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是微软公司提供的⼀个类库 (class libraries),以C++类的形式封装了Windows API,并且包含⼀个应⽤程序框架,以减少应⽤程序开发⼈员的⼯作量。其中包含⼤量Windows句柄封装类和很多Windows的内建控件和组件的封装类。主要⽤来开发windows下的桌⾯应⽤程序。 

1.3 QT发展及许可类型

QT诞⽣于1991年,后被诺基亚收购,⽬前为Digia公司所有,⽬前最新版本为6.0版 本,qt并⾏有两套开发框架c++ qt和qt Quick(qml)。
QT的许可类型:开源许可和商业许可(商业许可需要⽀付费⽤,允许开发者可以 不⽤根据开源协议要求开放的源代码,获得⽀持,使⽤模块上)。

⼆、QT环境搭建

2.1 获取安装包

获取qt跨平台集成开发环境Qt Creator可以从http://download.qt.io/ 获取,其中 qtcreator是打印⽹址如下所示:

archive->qt->5.14->qt…

2.2 安装QT

windows操作系统下,安装注意事项:
1.安装路径不能有中⽂,
2.安装过程中断⽹;(这样在输⼊账号界⾯可以点击Skip,不断⽹必须要输⼊⼀ 个账号)
3.组件选择

Qt5.9下常⽤组件说明:
编译器选择(必须选⼀个)
MSVC编译器:也就是微软的vc编译器,需要在电脑上安装visual studio的⽀持, 其中分为32位 和 64位版本
minGW编译器:也就是gcc编译器在Windows下作了封装,这个版本不需要VS环境 的⽀持,可以独⽴⽣成Windows平台的应⽤程序,MinGW是 Windows 平台上使 ⽤的 GNU ⼯具集导⼊库的集合(这⾥我们选择它)
Sources Qt 的源代码包,除⾮你想阅读 Qt 的源码,否则不⽤安装。
Qt Charts 是⼆维图表模块,⽤于绘制柱状图、饼图、曲线图等常⽤⼆维图表。 Qt Data Visualization 是三维数据图表模块,⽤于数据的三维显示,如散点的三 维空间分布、三维曲⾯等。
**Qt Scritp(Deprecated)**是脚本模块,已被抛弃,不建议安装。
其他Qt 的附加模块,⼤部分建议安装,这些附加模块括号⾥的 TP 是指 Technology Preview ,技术预览模块的意思,还处在功能测试阶段,不是正式版 模块;

附加模块括号⾥的 Deprecated 是指抛弃的旧模块,兼容旧代码使⽤的,⼀般⽤ 不到。

Tools下组件说明:
Qt Creator 4.3.1 ⽤于 Qt 程序开发的 IDE (必须安装)
MinGW 5.3.0 是 MinGW 编译⼯具链

  1. 将Qt的安装路径下…/bin 放置到系统的环境变量中。
    例如:我的安装路径C:\Qt\Qt5.14.2\5.14.2\mingw73_64\bin,赋值这个路径, 将其粘贴在环境变量值(path)的最后⾯ 。

2.3 安装部件说明

  • Qt Creator 4.11.1 (Community) :⽤于开发QT的IDE,是QT的主要⼯具,⾥边集成了调试 器,构建⼯具,编译器,界⾯设计器和帮助⽂档程序等。

  • Assistant 5.14.2 (MinGW 7.3.0 64-bit) 查看qt帮助⽂档的程序,Qt Creator也集成有 Designer 5.14.2 (MinGW 7.3.0 64-bit)

    独⽴进⾏窗⼝,对话框等界⾯设计的可视化程序,Qt Creator也集成有。设计出的界⾯是没有 功能的,

    如果需要完成相应的功能,还要与代码结合(界⾯⽂件可以通过uic⼯具转换成源码)。

  • Linguist 5.14.2 (MinGW 7.3.0 64-bit)

    编辑语⾔的资源程序,在开发多语⾔的应⽤程序界⾯会⽤到。

  • Qt 5.14.2 (MinGW 7.3.0 64-bit)

    qt的命令⾏⼯具,可以从命令⾏编译 Qt 程序(⽤qmake命令构建,make命令编译等)。

2.4 Qt Creator主界⾯简介

窗⼝的最上⽅为菜单栏,最左侧为主⼯具栏,中间部分为⼯作区。

2.5常⽤设置

  1. 配置⽂本编辑器
    ⼯具->选项->⽂本编辑器。可以在这⾥设置字体⼤⼩,相关颜⾊⽅案及字符编码。
    如果在代码编辑器中出现的注释或汉字乱码,可以尝试修改此处的⽂件编码。
  2. 设置界⾯的显示语⾔
    安装好的界⾯可能是中⽂,可能存在个别单词翻译不恰当,可以在该界⾯下将 Qt Creator的界⾯设置为英⽂。
  3. 选项下的Kits显示当前可⽤的编译⼯具,编译器和调试器

2.6常⽤快捷键及技巧

Ctrl+B 编译⼯程

Shift + F11 单步跳出函数

Ctrl+I ⾃动对⻬
F4 在 头⽂件(.h) 和 实现⽂件(.cpp) 之间进⾏切换。
F1 查看帮助
F2 跳转到函数定义(和Ctrl+⿏标左键⼀样的效果) Ctrl + / 注释/取消注释选定内容。

按住Ctrl 键,点击头⽂件 可以跳转到头⽂件的代码中。

三、Qt Creater初步使⽤

Qt creator 是⼀个集成开发环境,集合了编辑器、助⼿、构建器、设计器、编译器等。

(注意:创建⼯程的⽬录中不能有中⽂)

1)创建⼯程步骤

>>运⾏Qt Creator 程序

>>新建项⽬

>>选择项⽬模板

>>设置创建路径及项⽬名(不要含中⽂)

>>选择构建套件(选择qmake,qbs官⽅打算放弃)

>>创建源代码信息及选择基类

>>翻译⽂件(translation file)选择默认

>>配置默认编译器

>>点击完成按钮

应⽤程序类型说明:

Qt widget application ⽤于桌⾯应⽤程序开发

Qt console application ⽤于控制台应⽤程序开发;

Qt quick application ⽤QML语⾔开发,主要⽤于移动端开发;

⾮Qt项⽬的项⽬类型(Non-Qt Project)

  • 纯C⼯程;
  • 纯C++⼯程;

构建⼯具Cmake与qmake简介

构建⼯具或叫构建器负责把⼀个⽬录下的源码⽂件、头⽂件构建成⼀个Qt⼯程,

并且⾃动⽣成Makefile⽂件。

qmake 是 Qt 开发最核⼼的⼯具,是为 Qt 量身打造的,使⽤起来⾮常⽅便。

既可以⽣成 Qt 项⽬⽂件 .pro , 也可以⾃动⽣成项⽬的 Makefile ⽂件。

CMake(Cross platform Make)CMake是⼀个跨平台的、开源的构建⼯具。

cmake是makefile的上层⼯具,它们的⽬的正是为了产⽣可移植的makefile。

Qbs⼯具Qt打算放弃,不推荐⽤。

编辑器提供的基类选择说明:

QMainWindow 主窗⼝类,提供⼀个有菜单条、锚接窗⼝(例如⼯具条)和⼀ 个状态条的主应⽤程序窗⼝。

QWidget QWidgt类是所有⽤户界⾯对象的基类

QDialog QDialog类是对话框窗⼝的基类。

2 ) Qt ⼯程⽂件结构说明

1 .pro ⼯程(项⽬)管理⽂件,⽂件名是项⽬的名称。

qmake⼯具可以将此.pro⽂件⽣成Makefile

/*表示这个项⽬使⽤到的模块 
core 是qt的核⼼模块,其他模块都依赖着个模块, 
gui模块提供了窗⼝系统基础,事件处理,图形图形和⽂字及⽂本等。使⽤qmake构建项⽬时,core和gui 模块都是被默认包含的。 
*/
QT += core gui 

/*添加了widgets模块,这⾏代码的意思是:如果QT主版本⼤于4(也就是说当前使⽤的是Qt5或更⾼版 本), 
则需要添加widgets模块。 
Qt widgets模块中提供了经典的桌⾯⽤户界⾯的UI元素集合,简单来说所有C++程序⽤户界⾯部件都在 该模块中。*/ 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //如果主板本⼤于 4,则再添加 widgets 模块。 
CONFIG += c++11 # 使⽤c++11的特性 

#定义编译选项。QT_DEPRECATED_WARNINGS表示当Qt的某些功能被标记为过时的,那么编译器会发出 警告。 
DEFINES += QT_DEPRECATED_WARNINGS 

第16、20、23⾏分别是⼯程包含的源⽂件、头⽂件和界⾯⽂件。 
SOURCES += \ 
    main.cpp \ 
    mainwindow.cpp 
    
HEADERS += \ 
    mainwindow.h 
    
FORMS += \ 
    mainwindow.ui 
   
注释 从“#”开始,到这⼀⾏结束。

注意:

使⽤QT Creater打开⼯程中的.pro⽂件,会⾃动⽣成⼀个.pro.user⽂件,包含本

地的构建信息。如果要打开别⼈的⼯程⽂件,直接删掉pro.user⽂件,qtcreator

会重新创建。

  1. main.cpp (项⽬⼊⼝⽂件)

  2. .h .cpp 窗体相关的⽂件

在qt中任何窗体或组件都是⽤类封装的,⼀个类⼀般有⼀个头⽂件和⼀个cpp⽂

件。

  1. ui (界⾯⽂件)

Qt 提供的可视化Ui设计的界⾯⽂件,⽤⼀个xml格式存储窗体上的元件和布局

⽂件,最终在编译程序时由qt通过uic⼯具(界⾯编译器)进⾏解析转为为c++代

码。

例如下图cpp⽂件中的ui_mainwindow.h⽂件就是由.ui⽂件⽣成的,可以按住

Ctrl按键⽤

⿏标进⾏点击查看。

//图中mainwindow.cpp源码 
#include "mainwindow.h" 
#include "ui_mainwindow.h" //这个头⽂件是编译⽣成的与ui对应的mainwindow.ui对应的 类定义⽂件 

MainWindow::MainWindow(QWidget *parent) // 执⾏⽗类QMainWindow构造函数 
    : QMainWindow(parent) 
    , ui(new Ui::MainWindow) 
{ 
    ui->setupUi(this); //⽣成窗⼝和窗⼝的属性设置 
}

MainWindow::~MainWindow() //析构函数 
{ 
    delete ui; 
} 

双击⼯程中的.ui⽂件,显示QT界⾯设计器窗⼝如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZiP3DVhm-1673330864740)(picture\2.png)]

主要分为5个区域:
窗⼝部件盒:
主要包含布局、拉伸、按钮、视图(基于Model)、视图(基于Item)、容器、输
⼊控件、显示控件等。
窗⼝编辑器:
可以利⽤控件区的部件来对窗⼝进⾏布局,达到想要的效果。
对象查看器:
将窗体编辑区的控件按照⽗⼦关系以树形结构显示出来。与窗体编辑区的共同特 点是:可以改变对象名称、样式表、信号和槽等。
属性值编辑器:
可以编辑相应控件的属性值,例如:名称、⼤⼩、⽂本、样式等。
动作、信号/槽编辑器:
可以指定编辑动作及相应控件的信号与槽。

3)Qt类库模块简介

Qt类库⾥⼤量的类根据功能分为各种模块,这些模块⼜分为⼏⼤类。

15● Qt基本模块:提供Qt在所有平台上的基本功能。

● Qt附加⽊块:实现⼀些特定功能的提供附加价值的模块。

● 增值模块:单独发布的提供额外价值的模块或⼯具。

● 技术预览模块:⼀些处于开发阶段,但是可以作为技术预览使⽤的模块。

● Qt⼯具:帮助应⽤程序开发的⼀些⼯具⽐如QT的界⾯设计器。

基础模块:

Qt基本模块是Qt在所有平台上的基本功能,他们在所有的平台和⽬标平台上都可

以⽤。

其它模块⼀般不会被⾃动加⼊到项⽬中,如果需要在项⽬中⽤某个模块,则可以

在项⽬配置中添加此模块,例如Qt Network则需要在配置⽂件中加⼊:“QT +=

network”。

Qt附加模块:

Qt附加模块可以实现⼀些特定⽬的,这些模块可能只能在某些平台上有,或只能

⽤于某些操作系统,或只是为了向后兼容。⽤户安装时可以选择性的安装这些附

加模块。

四、第⼀个QT程序
  1. ⽤界⾯显示⼀个hello wold⽂字

⾸先创建⼀个带界⾯的⼯程,在⼯程的主程序中编写代码如下:

//创建⼀个Qt⼯程继承QMainWindow,主程序代码如下 
#include "mainwindow.h" 
#include <QApplication> 
#include <QLabel> 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); //实例化⼀个应⽤程序类对象,⽤于管理当前项⽬; 
    MainWindow w; //实例化⼀个窗⼝(窗体)类; 
    QLabel label(&w); //在w窗⼝对象上创建⼀个标签对象 
    label.setText("hello world"); //设置标签显示的内容 
    w.show(); // //显示窗⼝ 
    return a.exec(); //启动应⽤程序执⾏并进⼊使⽤程序的事件循环 
}

程序说明:

  • Qt 头⽂件没有.h 后缀

  • Qt ⼀个类对应⼀个头⽂件, 类名就是头⽂件名

  • QApplication 应⽤程序类

    QApplication类管理GUI应⽤程序的控制流和主要设置。 对于任何使⽤Qt的GUI应⽤程序,⽆论该应⽤程序在任何给定时间有0个,1个或更多个窗⼝,都只有⼀个QApplication对象。

  • a.exec() 启动应⽤程序执⾏并进⼊使⽤程序的事件循环 ,main()把控制权交给qt。

2、编译并运⾏程序

按CTRL+R或点击左下⻆的绿⾊三⻆图标编译并运⾏程序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9sw1FpCW-1673330864741)(picture\3.png)]

2)⽤界⾯设计器设计⼀个界⾯

⽤界⾯设计器添加⼀个便签并设置如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SZPVi8mx-1673330864741)(picture\4.png)]

mainwindow.h⽂件如下

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 
#include <QMainWindow> 

QT_BEGIN_NAMESPACE 
namespace Ui { class MainWindow; } 
QT_END_NAMESPACE 
    
class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 
        
public: 
    MainWindow(QWidget *parent = nullptr); 
    ~MainWindow(); 
    
private: 
    Ui::MainWindow *ui; 
};#endif // MAINWINDOW_H 

这是声明了⼀个名称为 Ui 的命名空间(namespace),包含⼀个类 Widget。但是这个类 Widget 并不是本⽂件⾥定义的类 Widget,⽽是 ui_widget.h ⽂件⾥定义的类,⽤于描述界⾯组件的.

mainwindow.cpp⽂件

#include "mainwindow.h" 
#include "ui_mainwindow.h" 

MainWindow::MainWindow(QWidget *parent) 
    : QMainWindow(parent) 
    , ui(new Ui::MainWindow) 
{ 
        ui->setupUi(this);//创建并设置界⾯ 
}

MainWindow::~MainWindow() 
{   //ui指针是this指针所指对象的⼀个数据成员 
    delete ui; //此处的ui指针代表的我们设计的界⾯对象,可以利⽤ui去访问界⾯中的button, label等等控件。 
} 

3)创建⼀个不带界⾯的程序

新建⼀个空的QT项⽬如下:

//non-qt project类型⼯程 
#include <iostream> 
using namespace std; 

int main() 
{ 
    cout << "Hello World!" << endl; 
    return 0; 
} 

在Qt中可以⽤cout进⾏输出,但是qt本身带的⼀些类型可能不⽀持,可能不会兼容Qt⾃带的⼀些类型,⽐如QByteArray,建议⽤qDegbug()函数实现输出。

五、Qt 的命名规则
  1. 类名: 单词⾸字⺟⼤写, 单词和单词之间直接连接, ⽆需连接字符

如: MyClass, QPushButton

class MainWindow

{ }

;

  1. 函数名字, 变量名: 第⼆个单词开始(不是从第⼀个单词开始) , ⾸字⺟⼤

写, 单词和单词之间直接连接, ⽆需连接字符

如:

void setFlag();

QString getText();

bool isDraw;

当使⽤多个单词命名名称时,QT采⽤“驼峰规则”,即每个单词的⾸字⺟⼤写。

  1. Qt 中内置的类型, 头⽂件和类命名同名。

如:

#include

QSring str;

#include

QWidget w;

4.全局常量和宏定义的名称全部⼤写,常量也尽量全部⼤写,并尽可能在类的作

⽤域内创建枚列举值;

六、帮助与调试

1)帮助获取

⾸先打开QT creator⼯具,然后点击左边导航的帮助按钮,其中提供的四个选项

进⾏选择,

分布是:

  • 书签:查看添加⾄书签的⻚⾯列表。
  • 内容:查找安装在开发电脑中的所有⽂档,来浏览⽂档内容。
  • 索引:基于所有已安装的⽂档中的关键字列表查找。
  • 打开⻚⾯,以查看当前打开的⽂档⻚⾯的列表。
  • 查找:在所有已安装的⽂档中进⾏查找。

​ 这⾥选择“索引查找”如下图所示:

​ 如果想要下次快速访问已经搜索到的内容,可以创建标签,在⼯具栏上点击

添加书签对应的图标。

  • 如果要查看某个⽅法或类的使⽤,可以将光标移动到函数或类上,然后按F1(笔记本Fn+F1),就可以跳转到对应的帮助⽂档,再按⼀次“F1”即可全屏显示帮助⽂档⻚⾯,按“Esc”即可退出帮助⽂档。
  • 公有成员函数:操作部件属性的相关函数。
  • 公有槽函数:Qt类中已经定义好的槽函数,直接可与信号相连接。
  • 信号:软中断,如按下按钮触发 pressed() 信号等。
  • 保护成员函数:通常事件所对应的虚函数放在此处。
  • 事件:常⽤事件,如操作⿏标触发的⿏标事件。

Public Slots:具有公开属性的槽函数,⾸先它具有某些功能的成员,但它可以与

信号绑定,除了可以被信号调⽤外,也可以被直接调⽤。

Signals:它们是以函数形式存在的,但它们并不实现出来,可以⽤emit显示的触发。

Reimplemented Protected Functions:可以重写的具有保护属性的成员函数。

Detailed Description:类的使⽤注意事项。

打开头⽂件或函数声明与定义的⽅法:

⿏标放在你需要打开的头⽂件或者函数声明的地⽅(如下图我⿏标放在MainWindow上)、Ctrl+⿏标左键单击(或者使⽤快捷键F2也可以),这样就可以跳转到头⽂件或者函数声明/函数定义的地⽅了。

2)调试程序

调试程序的⽅式:

1)系统中的调试⼯具

通过调试追踪变量变化和某个对象所调⽤到的⽅法

​ 1.设置断点

​ 2.选择调试菜单下的开始调试

​ 3.按F11单步调试,跳过按F10

​ 4.观察左边数据的变化和跟踪到的类

2) 使⽤qDebug()函数

​ 它可以将调试信息直接输出到控制台,使⽤时先包含头⽂件

#include。

例如: qDebug () << 123 << “hellow” << lable1 . text () << endl ;

qDebug()相当于c++中的cout,后⾯的使⽤规则都⼀样。

02QT基本数据类型

一、QT的基本数据类型

头文件包含了Qt类库的一些全局定义,包括基本数据类型、函数和宏
1)基本数据类型:
qint8
qint16

2)全局宏
Q_UNUSED(name)
QT_VERSION_STR
Q_DECL_OVERRID

3)常用函数:
qMax()
qMin()
foreach(variable, container)

4)QString类
>>QString是QT开发库里面的字符串处理类,主要对C++的字符串类型进行了封装
>>QString类提供了一个Unicode文本和经典的C以零结尾的字符数组的抽象。
>>QString存储字符串采用的是Unicode码,每一个字符是一个十六位的QChar

5)QString支持的操作符
QString支持的操作符号有:
用于字符串之间比较:“!=” “<” “<=” “==” “>=”
用于字符串之间传递:“+=” “=”

6)QString 与数值转换
● QString转整形
函数原型:int QString::toInt(bool * ok = nullptr, int base = 10) const
参数说明:
ok : 接收一个 bool 变量的指针,用于反馈转换过程是否成功
base:字符串对象转数字的进制基数
● QString转整形转double
double QString::toDouble(bool * ok = nullptr) const
● QString转整形转float
float toFloat(bool *ok = nullptr) const
● 数值类型-> QString
数值转Qstring 主要用到两个成员:

	 1.  QString & setNum(...)  普通成员函数。
	 1.  QString QString::number ( long n, int base = 10 ) [static]  静态成员函数
整数转QString     
QString & setNum(int n, int base = 10)   
参数n:需要转换的整数
参数base: 进制基数

​ 小数转QString
​ QString & QString::setNum(double n, char format = ‘g’, int precision = 6)
​ QString & setNum(float n, char format = ‘g’, int precision = 6)
​ 参数n:需要转换的float类型或double类的数值
​ 参数format: 转换之后的目标字符串格式(‘e’, ‘E’, ‘f’, ‘g’ , ‘G’) 其中,‘f’:定点数显示,
​ [-]9.9;e或E用科学计数法显示,使用g时 第三个参数表示有效数字的个数。
​ 参数precision:目标字符串显示的浮点数精度,默认是 6 。

7)QString的格式化输出
字符串的格式输出需要用到arg方法,其格式为:
● QString::arg ( int a, int fieldWidth = 0, int base = 10, const QChar & fillChar = QLatin1Char( ’ ’ ) ) const
说明:
参数1:是要填充的数字,
参数2:为最小宽度:
参数3:为进制,
参数4:为当原始数字长度不足最小宽度时用于填充的字符.
● QString::sprintf()也可以实现格式化输出。

8) 字符间转换
对于其他编码转为 QString,采用的是 QString::from* 静态公有成员函数,这些静态函数返回一个转
换好的 QString 对象以供使用。与之对应的是 QString 类对象的 to* 函数,QString 对象可以调用这些 to* 函数转出为其他编码格式的字符串。
QString --> 其他字符编码:

  1. toUtf8() QByteArray

  2. toLatin1() QByteArray //汉字不在latin1字符集中,转换汉字无意义。

  3. toLocal8Bit() QByteArray

说明:
● ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF。亦称为Latin1
● utf8字符集以2个或以上的字节表示一个汉字,遇到ASCII中的字符用一个字节表示
● Local8Bit()返回的是gb18030的字符集,它兼容gbk字符集,以两个字节表示一个文字。windows默认使用(GBK/GB2312/GB18030),unicode字符集以2个或以上的字节表示一个汉字。
其他编码字符  --> QString  :
● fromLocal8Bit()   toLocal8Bit()
● fromUtf8()   toUtf8() 
● fromLatin1()   toLatin1() 

 QString str="中国abc";
 qDebug()<<str.toUtf8()<<endl;
 qDebug()<<str.toLatin1()<<endl;
 //与操作系统及本地化语言相关,Linux 一般是 UTF-8 字符串,Windows 一般是 ANSI 多字节编码字符串。
 qDebug()<<str.toLocal8Bit()<<endl;

 QByteArray by=str.toUtf8();
 qDebug()<<QString::fromUtf8(by)<<endl;
 by=QString("ljs").toLatin1();
 qDebug()<<QString::fromLatin1(by)<<endl;
 "中国abc" 
 "ljs" 

----- QString与char *的转换----------------------------------
QString 转为标准库中的 string 类型,然后由string转char类型
QString filename;
string str = filename.toStdString();
const char* ch = str.c_str();
将 char * 转换为 QString 比较容易操作,我们可以使用 QString 的构造函数进行转换:
QString(const QLatin1String &str);

9)QByteArray
Qt 最常用的字符串类是内码固定的 QString,而针对传统类似 C 语言 char* 的字符串,
Qt 提供了 QByteArray 类来处理。

访问与修改:
QByteArray 的字节单元是 char,QByteArray 类可以用来存储原始的字节包含 '\0’和传统的以‘\0’ 结尾的传统字符串。
访问QByteArray: []、at()、data[]和constData[],其中at与最后一个为只读
添加元素:insert()方法
QByteArray by;
by.resize(3); //设置字节数组的元素个数;
by[0]=0x41; //赋值

类型转换:
QByteArray若为数值,可通过to**方法转为各种类型数据
toint()
转字符串:ByteArray ba(“Abcsdf中”);QString str=ba;
转换十六进制:tohex()

二、顺序容器

QT中主要的顺序容器有:QVector, QList,QLinkedList,QStack,QQueue。
QVector提供动态数组的功能,以下标索引访问数据;
QList是最常用的容器类,基于数组列表的形式实现的,优点是插入或删除效率高,查询效率差
QStack是提供类似于堆栈的后入先出操作的容器类,push()和pop()是主要的接口函数。
QQueue是提供与类似于队列先入先出操作的容器类,enqueue()和dequeue()是主要的操作函数。
必须要掌握的算法:

  1. 判空 Empty, isEmpty;
  2. 获取元素个数 size,count
  3. 清空 clear,
  4. 增加 append,insert,<<, …
  5. 删除 erase, removeOne,removeAll,removeAt,takeAt
  6. 查找 indexOf,value,[],at
  7. 修改 …
  8. 遍历

QStringList继承自QList,
提供了一个QString的List,它提供快速索引为基础的接入以及快速插入和清除。
其成员函数用于操作这个字符串列表如:
append(),insert(), replace(), removeAll(), removeAt(), removeFirst(), removeLast(), and removeOne()等

三、关联容器

QT提供的关联容器主要有:QSet,QMap,QMultiSet,QMultiMap,QHash。

四、迭代器

迭代器(iterator)为访问容器类里的数据项提供了统一的方法;
Qt有两种迭代器类:Java类型迭代器和STL类型的迭代器。
Java类型的迭代器更易于使用,且提供了一些高级的功能,而STL类型的迭代器效率更高。
对于每个容器类,都有两种Java风格的迭代器类型:一种是只读,另一种是可读写。

//迭代数组列表
QList list;
list << “A” << “B” << “C” << “D”;
QListIterator i(list);
while (i.hasNext())
qDebug() << i.next();
//说明:QListIterator没有提供从list中插入或移除项的函数,想要实现插入和移除,你必须使用QMutableListIterator

//迭代Qmap类型
QMap<QString, int>map; //定义QMap对象
map[“one”] = 1; // 添加元素,原集合不存在则添加元素,存在则修改元素
map[“two”] = 3;
map[“three”] = 17;
QMapIterator<QString, int> i(map);
while (i.hasNext())
{
i.next();//返回下一项
qDebug() << i.key()<<i.value()<<endl; //输出键和值
}

STL风格的迭代器
STL迭代器的API是以数组中的指针为模型的,比如++运算符将迭代器前移到下一项,*运算符返回迭代器所指的那一项。

容器只读迭代器可读写迭代器
QList, QQueueQList::const_iteratorQList::iterator
QLinkedListQLinkedList::const_iterator
QVectorQVector::const_iteratorQVector::iterator
QStack
QSet
QMap<Key, T>, QMultiMap<Key, T>QMap<Key, T>::const_iteratorQMap<Key, T>::iterator
QHash<Key, T>, QMultiHash<Key, T>

其他
● Qt还提供了一个关键字foreach(里定义的一个宏)用于方便地访问容器里所有数据项。
● 格式:foreach (varItem , Items)
foreach宏的参数依次为:元素类型,元素名,容器类型,容器名
QMap<QString, int>map; //定义QMap对象
map[“one”] = 1; // 添加元素,原集合不存在则添加元素,存在则修改元素
map[“two”] = 3;
map[“three”] = 17;

foreach( QString ele , map.keys()) // QString ele 就是遍历集合中每个元素的类型并存在在ele中
{
qDebug()<<ele<<“:”<<map[ele]<<endl;
}

03信号与槽

⼀、信号与槽简介

**信号与槽(Signal & Slot)**是QT⾃⾏定义的⼀种通信机制,也是 Qt 编程的基础。通过信号与槽的编程机制,使得 Qt 中处理界⾯各个组件的交互操作时变得更加直观和简单。

它独⽴于标准的C/C++语⾔,因此要正确的处理信号和槽,必须借助⼀个称为moc(Meta Object Compiler)的QT⼯具,该⼯具是⼀个C++预处理程序,它为⾼层次的事件处理⾃动⽣成所需要的附加代码。

信号(signal):就是特定情况下被发射的事件,⼀般由对象或空间发射出去的消息。

例如当⽤⿏标点击⼀个PushButton按钮就会发 射 clicked 信号。

槽(slot): 就是信号的响应函数或⽅法。

⽐如,按钮检测到⾃⼰被点击了⼀下,它就会发出⼀个信号(signal)。这种发出是没有⽬的的,类似⼴播。如果有对象对这个信号感兴趣,它就会使⽤连接(connect)函数,将想要处理的信号和⾃⼰的⼀个函数(称为槽(slot))绑定来处理这个信号。即当信号发出时,被连接的槽函数会⾃动被回调。

传统的GUI⼯具包中,窗⼝⼩部件(widget)都有⼀个回调函数⽤于响应它们能触发的每个动作,这个回调函数通常是⼀个指向某个函数的指针。但是,在QT中信号和槽取代了这些凌乱的函数指针,使得我们编写这些通信程序更为简洁明了。

⼆、信号与槽的连接

2.1 connect函数简介

connect 函数就是⽤来建⽴信号与槽之间的联系,QObject静态⽅法 connect 函数可⽤于信号和槽的连接:

**connect(const QObject sender, const char signal,

​ **const QObject receiver, const char method,

Qt::ConnectionType type = Qt::AutoConnection);

参数说明:

sender:发送者: ui->pushbutton

signal:发射的信号; clicked

receiver:接收者 ; ui->label1

method: 槽函数 ; &MainWindow::mysave_pro

type:指定信号与槽的连接⽅式

使⽤connect函数需要注意到的问题:

1)⽀持信号与槽机制的类必须从QObject类继承,同时在类的私有区设置Q_OBJECT宏;也就是说信号的发送者必须是QObject的派⽣对象。

2)信号可以有参数,当信号被发射时,信号的参数会被传递给相连接的槽函数;

3)槽函数的参数⼀般需要和信号相对应,但是参数可以⽐信号少,但是不能多;因为槽可以⾃动忽略⽆⽤的参数。

4)⼀个信号可以连接多个槽函数;多个信号可以连接⼀个槽函数;

5)⼀个信号可以连接到另⼀个信号;

6)在ui模式下添加的信号,在窗⼝xx.cpp中看不到connect函数,是因为系统使⽤了⾃动关联函数(ui_xxx.h可以看到QMetaObject::connectSlotsByName(MainWindow))也可

以⾃⼰显式在窗体类的构造函数中调⽤connect函数。

Qt::DirectConnection这个直接连接,我记得⼀般在对象与对象连接的时候才⽤,多线程中⼀般

都采⽤Qt::QueuedConnection这种⽅式。

//⽼式的链接⽅式 不推荐 缺陷:SIGNAL SLOT 将函数名字转换成字符串,不进⾏错误检查 connect(ui->lineEdit, SIGNAL(textEdited(QString)), ui->label, SLOT(setText(QString)));

2.2 创建槽函数

槽函数可以是任何成员函数、普通全局函数、静态函数,lambda表达式。但是⼀般都是定义为类的成员函数。

槽函数有QT写好的,也有可以⾃定义的槽函数。

1:⾃定义槽函数与系统槽函数使⽤

创建⼀个新⼯程名名为my_slot,并继承⾃mainwindow类,在桌⾯上添加两个按

钮,左边按钮对象名为btn1,右边按钮对象名为btn2。

>>在主窗体类mainwindow.h的头⽂件中声明⼀个槽函数

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 

#include <QMainWindow> 

QT_BEGIN_NAMESPACE 
namespace Ui { class MainWindow; } 
QT_END_NAMESPACE 
    
class MainWindow : public QMainWindow 
{ 
    Q_OBJECT //设置Q_OBJECT宏,有的话不⽤设置 
  
public: 
    MainWindow(QWidget *parent = nullptr); 
    ~MainWindow(); 
    
//-----------------------增加部分------------------------ 
public slots: 
    void mysolt(); //声明⼀个槽函数 
//--------------------------------------------------------- 
private: 
    Ui::MainWindow *ui; 
};#endif // MAINWINDOW_H

>>在mainwindow.cpp中定义槽函数

//实现⾃定义槽函数 
void MainWindow::mysolt()//实现类中声明的槽函数 
{ 
    qDebug()<<"进⼊槽函数"<<endl; 
    ui->btn2->setText("^_^"); //点击btn1按钮 改变btn2按钮⽂字 
}

>>在mainwindow.cpp的窗体类MainWindow的构造函数中进⾏连接。

按下左边按钮,将右边按钮设置为笑脸,按下右边按钮关闭当前窗体

//连接⾃定义槽函数 
connect(ui->btn1, &QPushButton::clicked, this, &MainWindow::mysolt); 
//使⽤系统⾃带的槽函数 
connect(ui->btn2, &QPushButton::clicked, this, &MainWindow::close);//close()是窗体的⾃带槽函数 
//注意:系统⾃带槽函数不需要我们声明和定义,直接可以拿来使⽤。可以在当前主窗体的⽗类 QWidget看到公共槽函数
  • 控件的槽函数⼀般会提供⼀部分,如果不能满⾜要求,可以在类中定义槽函数
  • 控件中⾃带的信号我们可以直接使⽤,即在connect中直接指定信号名
  • 控件中⾃带的槽函数我们可以直接使⽤,即在connect中直接指定槽函数

例2:⼀个信号可以对应多个槽函数

在⽂本框输⼊内容,两个标签内容跟着变化,将字体类型设置为宋体。

1.在窗体类的头⽂件中声明槽函数如下:

//窗体类 头⽂件 
public slots: 
    void PrintText1(const QString& text); //声明⼀个槽函数 
    void PrintText2(const QString& text); //声明⼀个槽函数

2.在窗体的cpp⽂件中实现槽函数如下:

//实现⾃定义槽函数 
void MainWindow::PrintText1(const QString &arg1) //实现类中声明的槽函数 
{ 
    // qDebug()<<arg1<<endl; 
    QFont ft;//设置字体为粗体 
    ft.setBold(true); 
    ui->label_1->setFont(ft); 
    ui->label_1->setText(arg1); 
}
//实现⾃定义槽函数 
void MainWindow::PrintText2(const QString &arg1) //实现类中声明的槽函数 
{ 
    ui->label_2->setText(arg1); 
    //qDebug()<<arg1<<endl; 
}

3.使⽤connect进⾏连接

//在窗体类的构造函数中调⽤connect函数 
connect(ui->lineEdit, &QLineEdit::textEdited, this,&MainWindow::PrintText1); 
connect(ui->lineEdit, &QLineEdit::textEdited, this,&MainWindow::PrintText2); 
//也可以利⽤标签⾃带的槽函数进⾏连接 
//connect(ui->lineEdit, &QLineEdit::textEdited, ui- >label_2,&QLabel::setText);

例3:⼀个槽函数对应多个信号

//在窗体头⽂件中声明⼀个槽函数 
public slots: 
    void PrintText(); //声明⼀个槽函数 

//在窗体的cpp⽂件中实现槽函数 
void MainWindow::PrintText() //实现类中声明的槽函数 
{ 
    QString strObjectSrc = this->sender()->objectName();// //获取信号源头对象的名称
    if(strObjectSrc=="btn1") 
        qDebug()<<"print:"<<strObjectSrc<<endl; 
    else if(strObjectSrc=="btn2") 
        qDebug()<<"print:"<<strObjectSrc<<endl; 
    else 
        qDebug()<<"other print:"<<strObjectSrc<<endl; 
}

//在窗体的构造函数中连接如下: 
connect(ui->btn1,&QPushButton::clicked, this, &MainWindow::PrintText); 
connect(ui->btn2,&QPushButton::clicked, this, &MainWindow::PrintText); 
connect(ui->btn3,&QPushButton::clicked, this, &MainWindow::PrintText);

例4:信号与槽的关联与解除

通过 disconnect函数可以实现解除关联,其参数和connect类似。

使⽤⾃动⽣成槽函数办法,在设计模式右击按钮,在右键菜单⾥点击“转到槽…”,为两个按钮的 clicked() 都添加各⾃的槽函数:

void MainWindow::on_btn_gl_clicked() 
{ 
    //进⾏关联 
    connect(ui->lineEdit, SIGNAL(textEdited(QString)), ui->label, SLOT(setText(QString))); 
}

void MainWindow::on_btn_jcgl_clicked() 
{ 
    //解除关联 
    disconnect(ui->lineEdit, SIGNAL(textEdited(QString)), ui->label, SLOT(setText(QString))); 
}

2.3 创建信号

QT内置了⼤量信号和槽,还⽀持⽤户⾃定义信号 和 槽

  • 在头⽂件的类中⽤Signal声明信号函数, ⽤法和似C++的关键词public、 private等

  • 只需声明,⽆需实现

  • 返回值为void

  • ⽀持带参,且可重载

    如果要信号函数是有 参数 的,可以通过 形参 给槽函数传值,但是槽函数的参数不能多于信号中的参数。

  • emit 可触发信号

注意:信号只是⼀个空壳,只需要声明它,⽽不要给它写实体代码。

例1:信号创建演示

当前窗体中的按钮发送⾃定义信号>>当前窗体的类中定义处理⾃定义信号的槽函数

1.在窗体类的头⽂件中声明槽函数如下:

//添加⾃定义的信号
signals:
    void SendMsg(QString str);//信号只需要声明,不要给信号写实体代码

public slots:
private slots:
    void on_btn_clicked(); //这个槽函数负责发送自定义的信号
    void PrintText(QString str);//定义信号及接受sengmsg信号的槽函数PrintText。

private:
    Ui::MainWindow *ui;
    Q_OBJECT //设置Q_OBJECT宏,有的话不用设置

2.在窗体的cpp⽂件中实现槽函数如下:

void MainWindow::PrintText(QString str)
{
    qDebug()<<"接收到自定义信号"<<endl;
    ui->label->setText(str);
}

void MainWindow::on_btn_clicked()
{
    //将文本框中输入的内容作为参数传给槽函数
    emit SendMsg(ui->lineEdit->text()); //发送信号
    qDebug()<<"发送信号"<<endl;
}

emit:

emit是不同窗口/类间的触发信号。
当对象改变其状态时,信号就由该对象发射 (emit) 出去,通过槽函数实现用户想要的效果。

3.使⽤connect进⾏连接

//发送信号为当前窗体,发送信号SendMsg 接收方为当前窗体,处理信号的槽函数为PrintText
connect(this,&MainWindow::SendMsg, this, &MainWindow::PrintText);
//由按钮的槽函数负责发送信号
connect(ui->btn,&QPushButton::clicked, this, &MainWindow::on_btn_clicked);

2.4 信号与槽传递⾃定义结构体

对于⾃定义的结构体参数,信号槽⽆法识别参数,导致信号槽连接不起作⽤。所以需要注册结构

体参数。在结构体中声明结束的地⽅加上结构体注册。

struct DealDetailInfo 
{
};
Q_DECLARE_METATYPE(DealDetailInfo); 

注册⾃定义数据类型⽅法步骤分为三步:

1)加⼊头⽂件:

#include

2)添加声明:

Q_DECLARE_METATYPE(YOURS_STRUCT);

3)注册:

qRegisterMetaType(YOURS_STRUCT);

如果要使⾃定义类型或其他⾮QMetaType内置类型在QVariant中使⽤,

必须使⽤该宏Q_DECLARE_METATYPE如果⾮QMetaType内置类型要在信号与槽中使⽤,必须

使⽤qRegisterMetaType。

04界面组件及界面布局

⼀、其他窗⼝部件

1.1 常⽤控件简介

控件是界⾯设计的基本部件,QT对控件根据功能进⾏了分组,主要的分组有:

1、按钮组

从上到下依次是:按钮、⼯具按钮、单选按钮复选框、命令链按钮、对话框按钮盒。

在这里插入图片描述

2、输⼊部件组

依次为:组合框、字体组合框、⾏编辑框⽂本编辑框、纯⽂本编辑框、数字显示框、双⾃旋盒。从Time Edit控件开始从上到下:时间编辑、⽇期编辑、⽇期/时 间编辑、拨号、横向滚动条、垂直滚动条、横向滑块、垂直滑块、按键序列编辑 框。

在这里插入图片描述

3、显示控件组

从上到下:标签、⽂本浏览器、图形视图、⽇历、液晶数字、进度条、⽔平线、 垂直线、开放式图形库⼯具、嵌⼊式QML⼯具。

在这里插入图片描述

4、空间分割组

在这里插入图片描述

5、布局管理组

垂直布局、横向布局、⽹格布局、表单布局

在这里插入图片描述

6、容器组

组框、滑动区域、⼯具箱、标签⼩部件、堆叠部件、帧、⼩部件、MDI区域、停靠窗体部件、封装Flash的ActiveX控件

在这里插入图片描述

7、项⽬视图组

清单视图、树视图、表视图、列视图

在这里插入图片描述

1.2 QLabel标签控件

QLabel 是我们最常⽤的控件之⼀, 可以⽤来显示⽂本(普通⽂本,html), 图⽚和动画等。继承关系:QLabel—>QFrame—>QWidget

  • 通过 QLabel 类的 setText 函数设置显示的内容:

    void setText(const QString &)

例1:显示⽂本内容

QLabel *label = new QLabel;
label->setText("Hello, World!" );
label->show();
//---------------也可以通过构造函数设置标签⽂本
QLabel *label=new QLabel("hello world");

//可以显示 HTML 格式的字符串
MainWindow w;//定义⽗窗⼝
QLabel * label = new QLabel(&w);//设置标签的⽗对象
label ->setText("Hello, World");
label ->setText("<h1><a href=\"https://www.baidu.com\"> 百度⼀下</a></h1>");
label ->setOpenExternalLinks(true);
w.show()

其中 setOpenExternalLinks()函数是⽤来设置⽤户点击链接之后是否⾃动打开链接, 如果参数指定为 true 则会⾃动打开,如果设置为 false, 想要打开链接只能 通过捕捉 linkActivated()信号。

  • 可以使⽤ QLabel 的成员函数 setPixmap 设置图⽚

    void setPixmap(const QPixmap &)

例2:QLable显示图⽚

QLabel * label = new QLabel;
QPixmap pixmap; //⾸先定义 QPixmap 对象
pixmap.load("D:\\led.bmp"); //加载图⽚
label->setPixmap(pixmap); //将图⽚设置到 QLabel 中
label->show();
// 设置头像
QPixmap pixmap(":/壁纸/1.jpg");
//固定size
pImageLabel->setFixedSize(90, 90);
pImageLabel->setPixmap(pixmap);

QPixmap主要⽤于在屏幕中显示图像;针对屏幕显示⽽最佳化设计,QImage主 要是为图像I/O、图⽚访问和像素修改⽽设计的。

  • 设置标签⽂本的字体属性

设置字体主要使⽤的是QFont对象,然后使⽤setFont⽅法进⾏标签⽂本字体设置

void setFont ( const QFont &);

MainWindow w;

QFont ft; //QFont("宋体",20,QFont::Bold)
ft.setFamily("微软雅⿊"); //设置字体类型
ft.setBold(true); //设置字体加粗,封装的setWeight函数
ft.setPointSize(20); //设置字体⼤⼩
ft.setItalic(true); //设置斜体
ft.setUnderline(true); //设置字体下划线

QLabel * label = new QLabel(&w);
label->setFont(ft);
label->resize(200,50);
label->setText("hello world");

w.show();
  • 设置标签⽂本的字体颜⾊

设置颜⾊有两种⽅式,⼀种利⽤调⾊板,⼀种设置setStyleSheet;

1)使⽤调⾊板举例

调⾊板它管理着控件或窗体的所有颜⾊信息,每个窗体或控件都包含⼀个 QPalette对象,在显示时按照它的QPalette对象中对各部分各状态下的颜⾊的描 述来进⾏绘制。

void setPalette ( const QPalette &);

说明:

QPalette类的ColorRole常⽤的有:

QPalette::Window ⼀个常规的背景颜⾊

QPalette::WindowText ⼀个⼀般的前景颜⾊

QLabel * label = new QLabel;
QPalette pe;
pe.setColor(QPalette::WindowText, Qt::red);//设置颜⾊
label->setPalette(pe);
label->setText("hello world");
label->show();

注意:如果是不常⽤颜⾊可以⽤通过QColor类传⼊对应的 rgb值来设置
例如:pe.setColor(QPalette::Window, QColor(color));

2)使⽤样式表举例

lineEdit.setStyleSheet(“color:red”);//⽂本颜⾊

lineEdit.setStyleSheet(“background-color:red”);//背景⾊

QLabel *lable = new QLabel;
lable ->setStyleSheet("color:orange;"); //设置字体为橙⾊
//lable ->setStyleSheet("background-color:green");//设置背景⾊
lable ->setText("hello world");
lable ->show();

其他⽅法如:void move(int x, int y); 设置标签在⽗对象上的坐标位置。

1.3 QLineEdit 单⾏输⼊控件

QLineEdit是Qt 提供的单⾏⽂本编辑框。

  • 设置编辑框的内容

void setText(const QString &)

  • 获取编辑框的内容

QString text() const

  • 使⽤ QLineEdit 类的 setEchoMode () 函数设置⽂本的显示模式,

函数声明:void setEchoMode(EchoMode mode)

EchoMode 是⼀个枚举类型,⼀共定义了四种显示模式:

QLineEdit::Normal 模式显示⽅式, 按照输⼊的内容显示。

QLineEdit::NoEcho 不显示任何内容, 此模式下⽆法看到⽤户的输⼊。

QLineEdit::Password 密码模式, 输⼊的字符会根据平台转换为特殊字符。

QLineEdit::PasswordEchoOnEdit 编辑时显示字符否则显示字符作为密 码。

  • setReadOnly()设置能否编辑
  • setMaxLength()设置可以输⼊的最多字符数
  • setPlaceholderText()设置提示⽂字

例如: LineEdit->setPlaceholderText( “电影、影⼈、影院、电视剧” );

相关信号:

  • ⽂本改变时会发出 textChanged() 信号;
  • 如果不是由setText()造成⽂本的改变,会发出textEdit()信号;
  • 当编辑结束,或者LineEdit失去了焦点,或者当返回/回⻋键按下时, editFinished()信号将会发出

例1:计算器程序

int a1=ui->op1->text().toInt(); //qstring 转int
int a2=ui->op2->text().toInt();
//qDebug()<<a1<<a2<<endl;
QString r=QString::number(a1+a2); //将int转qstring
ui->result->setText(r);
//两个信号对⼀个槽实现
connect(ui->op1,&QLineEdit::textEdited,this,&my_gui::get_result);
connect(ui->op2,&QLineEdit::textEdited,this,&my_gui::get_result);
void my_gui::get_result()
{
a1=ui->op1->text().toInt();
a2=ui->op2->text().toInt();
QString r=QString::number(a1+a2);
ui->result->setText(r);
}

//写在构造函数中
ui->lineEdit->setEchoMode(QLineEdit::Password);
ui->result->setStyleSheet("background-color:green");

1.4 QTextEdit 多⾏富⽂本编辑控件

QTextEdit 是⼀个多⾏⽂本编辑器,⽤于显示和编辑多⾏简单⽂本,可以显示⼤的 html⼦集,包括表格,⽂字和图像。

重要⽅法:

  • 插⼊⽂本块:insertPlainText();
  • 插⼊html格式⽂本块:>insertHtml()
  • 获取控件中输⼊的内容:>toPlainText()
  • 设置是否只读 setReadOnly()
//写入构造函数中

ui->textEdit->insertPlainText("dsfdsfdsfsdfsdfdsfsdfdsfsdfsdfdsfdsfds");
//保留原内容然后插⼊
ui->textEdit->setText("jdfs");//先清空后插⼊内容
QFont font;
font.setPointSize(16);
font.setBold(true);
ui->textEdit->setCurrentFont(font);//设置当前字体
ui->textEdit->insertPlainText("hello world\n");
ui->textEdit->insertPlainText("hello world1\n");
//读取⽂本框中的内容
qDebug()<<ui->textEdit->toPlainText()<<endl;
ui->textEdit->insertHtml("<img src=\"d:\\ak00.bmp\" />");

1.5 QPushButton 普通按钮

按钮控件常⽤编辑属性说明:

继承⾃QAbstractButton,为QAbstractButton提供按钮的通⽤性功能,此为抽象 基类,所以⽆法进⾏实例化。

• objectname 设置对象的名称

• enabled 设置按钮是否可⽤

• geometry 设置按钮的尺⼨及在⽗窗体中的坐标位置

• font 设置字体⼤⼩

• cursor 设置⿏标在空间表⾯的显示图标形式

• text 设置按钮表⾯的⽂字内容

• icon 给按钮设置⼀个⼩图标(从⽂件中选择⼀个icon格式的图⽚)

• tooltip 当⿏标移动到空间区域上时显示设置的⽂本内容

• stylesheet 设置字体的颜⾊,字体等。

• shortccut 给按钮设置快捷键触发

• autoExclusive:bool 标志⾃动互斥是否激活enabled

常⽤⽅法:给按钮设置名字 setText()

按压按钮被点击之后会触发 clicked 信号:

void QAbstractButton::clicked(bool checked = false) 注意:这⾥参数⽆意义。

static bool a=true;
a=!a;
ui->pushButton2->setEnabled(a);

QIcon my;
my.addFile("d:\\qq.png");
ui->pushButton2->setIcon(my);

1.6 QRadioButton单选按钮

QRadioButton 是单选按钮,当有多个 QRadioButton 控件存在时,只能选中⼀ 个,单选框的外观⼀般是⼀个空⽩的圆洞。⽽在它的旁边则通常有⼀个⽂字的标签。

单选按钮类构造函数:

QRadioButton(const QString &text, QWidget *parent = nullptr)

QRadioButton(QWidget *parent = nullptr)

  • 单选按钮有选中和⾮选中两种状态,获取当前状态通过函数:

bool isChecked() const

  • 设置单选按钮的状态

void setChecked(bool) //设置true选中,false表示未选中

// ui->radioButton->setChecked(true);设置选中,传false表示未选中
if( ui->radioButton->isChecked())
{
    ui->radioButton->setText("已被选中");//setText()⽅法设置单选按钮标题
}
else
{ 
    ui->radioButton->setText("未被选中");
}

常⽤信号:

void toggled(bool checked)

说明:只要单选按钮的状态发⽣变化,这个信号就会触发,其中参数表示选择还 是不选中触发信号。

单选按钮分组:

在⼀个窗体⾥⾯,默认所有的单选按钮都是互斥的,如果需要⽤多组,可以使⽤复选框QGroupBox或者⼿动编写代码(QButtonGroup类实现)实现分组。推荐使⽤后者实现,因为它仅仅是⼀个容器,不会有任何视觉表现。

在窗体头⽂件中定义 QButtonGroup类型成员指针变量
private:
//按钮分组
QButtonGroup *sex_group; //性别单选按钮分组
QButtonGroup *class_group; //课程单选按钮分组

在窗体构造函数中添加
//新建性别虚拟分组,并添加按钮和id
sex_group = new QButtonGroup(this); //声明⼀个容器
sex_group->addButton(ui->radio_man, 0); //男
sex_group->addButton(ui->radio_woman, 1); //⼥

class_group = new QButtonGroup(this); //声明⼀个容器
class_group ->addButton(ui->radio_math, 0);
class_group ->addButton(ui->radio_ch, 1);
class_group ->addButton(ui->radio_en, 2);

1.7 QCheckBox复选按钮

复选框的选项就是多选题,⽽之前单选框是单选题。这两种按钮应⽤都很⼴泛, 遇到可以选择多个选项时,复选框就派上⽤场了。

主要⽅法有:

text() :获取⽂本

setText():设置⽂本

bool isChecked() const :获取当前的状态(选中与⾮选中)

void setChecked(bool) :设置复选框的状态

复选框状态变化时,会发出信号:

void toggled(bool checked)

1.8 Combo Box下拉框

Combo Box是Qt下拉菜单的控件,⽤户可以⼿动输⼊数据,也可以从数据列表选 择⼀个条⽬作为输⼊数据。在ui界⾯可以点击右键 编辑项⽬ 添加下拉列表中的内容。

常⽤的⽅法有:

addItem()或者addItems() 添加数据项:

clear(); 清除组合框所有项

item.count( ) 返回item数⽬

item.currentIndex( ) 返回当前返回索引(从0开始)

item.currentText( ) 返回当前选择内容

item.itemText(index) 返回当前index的内容

item.setCurrentIndex( index ) 设置index为当前选择

setEditable( true ) 设置选框可编辑

setEditText( string ) 设置编辑框内容

setItemText( index,string) 设置index内容为string

常⽤到的信号:currentTextChanged(QString),当Combo Box对象当前值发⽣ 改变时,会激发上⾯的信号函数。

QList<QString> q={"12","23","50","100"};
for(int i=0;i<q.count();i++)
ui->comboBox->addItem(q[i]);
或者
QStringList fonts = { "Arial", "Helvetica", "Times" };
ui->comboBox->addItems(fonts);

1.9 ⽇期时间类

QT获取时间的类有3个,分别是QDate、QTime、QDateTime, 属于QT的network模块。

⼀、QDATE类提供⽇期函数:

QDATE对象包含公历中的⽇历⽇期,即年、⽉和⽇数。它可以从系统时钟读取当前⽇期。它提供了⽐较 ⽇期和操作⽇期的功能。

QDate::currentDate()从系统时钟读取当前⽇期。

例如:QDate::currentDate().toString(“yyyy.MM.dd”)

QTime::currentTime()获取时间为时分秒,

例如: QTime::currentTime().toString(“hh:mm:ss:zzz”)

QTime time = QTime::currentTime();
qDebug() << time.toString("hh:mm:ss");
ui->label->setText(time.toString("hh:mm:ss"));

1.10 容器类控件

容器部件就是可以在部件内放置其他部件的部件,常⽤的有GroupBox,tab widget和窗体类控件(放后边讲)。

1)GroupBox

GroupBox分组框是⼀个对多个部件进⾏编组的框架容器,⽤于将多个围绕同⼀主 题的部件在分组框内编组,便于对这些⼦部件进⾏排列编组和布局管理。

注意:分组框不⽀持⾃动布局,如果要⽀持分组框内组件的⾃动布局,可以在分 组框内先放置布局部件,再在布局部件内部署其他组件

QGroupBox *setting_group_box = new QGroupBox(("Setting"));
//QHBoxLayout *setting_layout = new QHBoxLayout();⽬的是让其⾃动布局
setting_group_box->setLayout(setting_layout);

QCheckBox *check_box1 = new QCheckBox(("CheckBox1"));
QCheckBox *check_box2 = new QCheckBox(("CheckBox2"));
QCheckBox *check_box3 = new QCheckBox(("CheckBox3"));
setting_layout->addWidget(check_box1);
setting_layout->addWidget(check_box2);
setting_layout->addWidget(check_box3);

2)tab widget

QTabWidget类提供了⼀组选项卡式⼩部件。 选项卡⼩部件提供了⼀个选项卡栏(参⻅QTabBar)和⼀个“⻚⾯区域”,⽤于显示与 每个选项卡相关的⻚⾯。默认情况下,选项卡栏显示在⻚⾯区域的上⽅,但是可 以使⽤不同的配置(参⻅表)。每个选项卡都与不同的⼩部件(称为⻚⾯)相关联。在 ⻚⾯区域中只显示当前⻚⾯;其他⻚⾯都隐藏起来了。⽤户可以通过单击选项卡或 按Alt+字⺟快捷键(如果有的话)来显示不同的⻚⾯。可以使⽤setTabEnabled()设 置每个选项卡在任何给定时间都是启⽤或禁⽤的。

重要信号:当⽤户选择⼀个⻚⾯时,会发出currentChanged()信号。

1.11 列表类控件

QListWidget类也是GUI中常⽤的类,它从QListView下派⽣:

常⽤⽅法和属性:

(1)添加⼀项或多项。

void addItem ( const QString & label )

void addItem ( QListWidgetItem * item )

void addItems ( const QStringList & labels )

(2)包含隐藏的列表项在内的列表项总数。

int count () const

(3) 返回当前选择的项。

QListWidgetItem * currentItem () const

(4)删除指定项item。

void removeItemWidget ( QListWidgetItem * item )

重要信号:itemClicked()表示当某⾏被点击后发出该信号

1.12 表格控件

QTableWidget是QT程序中常⽤的显示数据表格的控件,QTableWidget是 QTableView的⼦类,主要的区别是QTableView可以使⽤⾃定义的数据模型来显 示内容(也就是先要通过setModel来绑定数据源),⽽QTableWidget则只能使⽤标 准的数据模型,并且其单元格数据是QTableWidgetItem的对象来实现的(也就是不 需要数据源,将逐个单元格内的信息填好)。

创建表格:

#include <QTableWidget>
#include <QHeaderView>

MainWindow w;
QTableWidget* table = new QTableWidget(&w); //在主窗⼝上创建⼀个表格
table->setRowCount(3); //设置⾏数
table->setColumnCount(2); //设置列数
//table->setWindowTitle("QTableWidget & Item"); 表格做独⽴界⾯可设置表格窗⼝名称
table->resize(500,600); //设置表格的显示⼤⼩

QStringList header;
header<<"姓名"<<"年龄";
table->setItem(0,0,new QTableWidgetItem("张⻜")); //设置表格内容
table->setItem(0,1,new QTableWidgetItem("12")); //设置表格内容

设置表格的宽度与对⻬

table->setColumnWidth(1,200); //设置列宽
table->setRowHeight(1,60); //设置⾏⾼
//还可以将⾏和列的⼤⼩设为与内容相匹配
tableWidget->resizeColumnsToContents();
tableWidget->resizeRowsToContents();

QHeaderView *headerView = horizontalHeader();
headerView->setMovable(false);//去除表头的移动
headerView->resizeSection(0,284);//设置第⼀列宽
headerView->resizeSection(1,127);//设置第⼆列宽
columnHeaderItem0->setTextAlignment(Qt ::AlignCenter);//设置表头的对⻬⽅式

设置表格禁⽌编辑与选择模式:

在默认情况下,表格⾥的字符是可以更改的,⽐如双击⼀个单元格,就可以修改原来的内容,如果想禁⽌⽤户的这种操作,让这个表格对⽤户只读,

table->setEditTriggers(QAbstractItemView::NoEditTriggers);
//设置表格为整⾏选择
table->setSelectionBehavior(QAbstractItemView::SelectRows); //整⾏选中的⽅式

QAbstractItemView.SelectionBehavior枚举还有如下类型
Constant Value Description
QAbstractItemView::SelectItems 0 Selecting single items.选中单个单元格
QAbstractItemView::SelectRows 1 Selecting only rows.选中⼀⾏
QAbstractItemView::SelectColumns 2 Selecting only columns.选中⼀列

获取指定单元格内容: table->item(0,0)->text();

QTableWidget::clearContents() 函数清除表格数据区的所有内容,但是不清除表头。

QTableWidget::rowCount() 函数返回表格数据区的⾏数。

获得单击单元格的内容

通过实现 itemClicked (QTableWidgetItem *) 信号的槽函数,就可以获得⿏标单击到的单元格指针, 进⽽获得其中的⽂字信息 *

connect(tableWidget,SIGNAL(itemDoubleClicked(QTreeWidgetItem ,int)),this,SLOT(getItem(QTr eeWidgetItem* ,int)));

二、QT的布局管理

界⾯开发⾸先要对整个界⾯进⾏布局,使窗体上的所有的控件必须有⼀个合适的 尺⼨和位置。使⽤这些Qt布局管理类的另⼀个原因是,在程序、系统改变字体, 语⾔或者在不同的平台上运⾏时,布局管理器能够⾃动调整窗体⾥所有控件的⼤ ⼩和尺⼨。这些⽅法可以嵌套使⽤。

常⽤的布局⽅法:

(1)使⽤⽔平布局类QHBoxLayout;

(2)使⽤垂直布局类QVBoxLayout;

(3)使⽤⽹格布局类QGridLayout;

(4)使⽤表格布局类QFormLayout;

(5)使⽤分组布局类QStackLayout( QStackedLayout类把⼦控件进⾏分组或者 分⻚,⼀次只显示⼀组或者⼀⻚,隐藏其他组或者⻚上的控件)。

2.1传统的绝对布局

设置窗⼝⼤⼩:void setGeometry(int x, int y, int w, int h)

其中:x 和 y 是控件距离⽗窗⼝左上⻆的坐标,w 是宽度,h 是⾼度

如果不移动窗⼝左上⻆坐标,只改变窗⼝的尺⼨⼤⼩:void resize(int w, int h) 设置窗体的固定⼤⼩:void setFixedSize(int w, int h)。

2.2 ⽔平与垂直布局器

(1)使⽤⽔平布局类QHBoxLayout

将内部的控件按照⽔平⽅向排布,⼀列⼀个

(2)使⽤垂直布局类QVBoxLayout;

将内部的控件按照垂直⽅向排布,⼀⾏⼀个。

布局⽅法主要有两种:

1、先拖⼊布局器,然后再将控件拖⼊到布局器中

2、先放⼊控件,然后选中需要布局的控件再进⾏布局(后者更常⽤) 先放置控件>>然后选中需要布局的空间>>然后拖⼊布局管理器>>进⾏拖拉调整 完了之后,在选择各部分的布局管理器在进⾏整体布局(布局管理器可以嵌套)

与布局紧密关联的是两个空⽩条(或叫弹簧条):Horizontal Spacer ⽔平空⽩条 和 Vertical Spacer 垂直空⽩条,空⽩条的作⽤就是填充⽆⽤的空隙,如果不希望看到控件拉伸后变丑,就可以塞⼀个空⽩条到布局器⾥⾯,布局器通常会优先拉伸空⽩条。

需要注意的是:布局器仅⽤于辅助功能,帮助⾃动调整窗⼝⾥的控件布局,并不 是实体控件,没有 show() 之类的显示函数,不能单独存在,必须要有实体控件才能设置布局器。

打破布局:选中所有的控件和布局器,它就打破所有的布局器,只剩下普通控件。打破所有布局后,回到没有布局器的状态。

代码实现⽔平或垂直布局相关函数:

布局器是⼀定要往⾥⾯添加控件才有⽤,添加控件的函数如下:

void addWidget(QWidget * widget, int stretch = 0, Qt::Alignment alignment = 0)

void insertWidget(int index, QWidget * widget, int stretch = 0, Qt::Alignment alignment = 0)

⽔平布局器 QHBoxLayout 和垂直布局器 QVBoxLayout 的基类都是 QBoxLayout。

2.3 ⽹格布局器

当控件分布的⾏、列都⽐较有规律时,可以不⽤⼀⾏⾏设置布局器,⽽是直接⽤⽹格布局器设置所有的⾏和列。⽹格布局器⾥⾯的控件既可以占⼀个格⼦, 也可 以占据 rowSpan * columnSpan 连续多⾏多列的位置。

⽹格布局器的⾏、列尺⼨可以均匀分布,也可以⾮均匀分布,通常由尺⼨调整的伸展策略和伸展因⼦灵活控制。

2.4 表单布局器

表单布局器⼜叫双列表格布局器。

对于接收⽤户输⼊的窗体(⽹⻚设计中对应称之为表单), 通常是每⾏⼀个标签 ⽤于提示信息、⼀个输⼊控件接收⽤户输⼊, QFormLayout 就是对这种每⾏两列 的控件分布进⾏建模并简化界⾯的构建过程。表单布局器的规律性、限制性⽐⽹ 格布局器更强,是严格的两列布局,通常第⼀列固定是标签,第⼆列是输⼊控件 或 者输⼊控件组合成的布局器。

表单布局器中每⾏的控件或⼦布局器都有特定的⻆⾊,表单布局器的第⼀列称为 标签,⻆⾊为 QFormLayout::LabelRole;第⼆列称为域,或叫字段,⻆⾊为 QFormLayout::FieldRole。

如果表单布局器某⼀⾏的两列空间全部由单独⼀个控件或⼦布局器占据,那么这 个控件或⼦布局器的⻆⾊就称为 QFormLayout::SpanningRole,可以叫跨越⻆⾊。

与⽹格布局的代码对⽐,对于两列的控件,使⽤表单布局器的代码⽐⽹格布局器节省很多代码。

QFormLayout *formLayout = new QFormLayout;
formLayout->addRow(tr("&Name:"), nameLineEdit);
formLayout->addRow(tr("&Email:"), emailLineEdit);
formLayout->addRow(tr("&Age:"), ageSpinBox);
//virtual QLayoutItem * takeAt(int index) 删除某个控件
setLayout(formLayout);//setLayout() 是把第 row ⾏的 role ⻆⾊的格⼦内容设置为新的 layout

2.5 分裂器

之前布局器中控件⼤⼩是根据窗⼝⼤⼩⾃动调整,⽤户能拉伸窗⼝但是不能直接 拉伸界⾯内部的某个控件。 ⽽分裂器是将每个控件的⼤⼩调整都交给⽤户⼿动控制,⽤户能在程序运⾏时⾃由调整分裂器内各个控件的⼤⼩,并能⾃动隐藏缩到很窄或很扁的控件,为其他控件腾出显示空间。

分裂器 QSplitter 是⼀个实体功能控件,它的基类是 QFrame,QFrame 基类正是 QWidget。主要有⽔平分裂器和垂直分裂器。

qt designer如何调整布局中button的⼤⼩?

调整属性⾥⾯的:

minimumSize 最⼩⼤⼩,分height和width

maximumSize 最⼤⼤⼩,分height和width

锁定按钮的变化范围

结合控件的SizePolicy属性,来控制布局管理中的控件的尺⼨⾃适应⽅式。⼀些常⽤值的含义:

Fixed:控件不能放⼤或者缩⼩,控件的⼤⼩就是它的sizeHint。

Minimum:控件的sizeHint为控件的最⼩尺⼨。控件不能⼩于这个sizeHint,但是可以放⼤。

Maximum:控件的sizeHint为控件的最⼤尺⼨,控件不能放⼤,但是可以缩⼩到它的最⼩的允 许尺⼨。

Preferred:控件的sizeHint是它的sizeHint,但是可以放⼤或者缩⼩

Expandint:控件可以⾃⾏增⼤或者缩⼩

注:sizeHint(布局管理中的控件默认尺⼨,如果控件不在布局管理中就为⽆效的值)

05窗体设计

⼀、窗体部件简介

在所有的图形界⾯中,都是由窗⼝和窗⼝组件构成的,在QT中头⽂件包 含窗⼝组件,对应Qt中的GUI模块,并且Qt中以组件对象的⽅式构建图形⽤户界⾯。

Qt Creator 提供的默认基类只有 QMainWindow、QWidget 和 QDialog ,这3种 窗体类也是以后使⽤最多的。

QMainWindow 是带有菜单栏和⼯具栏的主窗⼝类。

QDialog 是各种对话框的基类,⽽它们全部继承⾃ QWidget。

其实所有的窗⼝部件都继承⾃ QWidget,QWidget 类是所有⽤户界⾯对象的基 类,被称为基础窗⼝部件:

在上图中可以看到,QWidget 继承⾃ QObject 类和 QPaintDevice 类,其中 QObject 类是所有⽀持Qt对象模型(Qt Object Model)的基类,QPaimDevice 类是所有可以绘制的对象的基类。

Qt中没有⽗组件的顶级组件叫做窗⼝,与其相对的是⾮窗⼝部件,⼜称为⼦部件。

例1:利⽤基础窗体类QWidget创建第⼀个窗体,并在其上放⼀个标签⼦部件 先创建⼀个空的qmake⼯程如下图所示:

#include "mainwindow.h"
#include <QtWidgets>
#include <QLabel>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("This is a fst UI"); //设置窗⼝标题
    //不设置窗⼝⼤⼩。默认窗⼝就是其⼦部件的⼤⼩
    //w.setGeometry(0,0,400,300); //设置控件的坐标,四个参数分别代表(X坐标,Y坐标,控件宽,控件⾼)。
    QLabel label(&w); //设置⽗类为w
    label.setText("This is a QLabel");
    label.resize(50,20); //改变部件的⼤⼩, 或⽤.setGeometry改变⼤⼩
    w.show(); //在屏幕上显示出来
    return a.exec();
}
⼆、主窗体设计

主窗⼝设计通常是应⽤程序界⾯设计的第⼀步,主窗⼝主要分为窗⼝标题,菜单 栏,⼯具栏和状态栏这四个部分,只要在程序设计中分别对四个项⽬进⾏设计就 可以实现主窗⼝的编程。

在使⽤ Qt开发GUI的程序中,窗⼝操作是⼀件频率很⾼的事,常⻅的窗⼝操作函 数有:

  • setWindowTitle()设置窗⼝的标题
  • geometry() 设置⼏何尺⼨(位置+⼤⼩),不包含窗⼝装饰器。
  • resize() 只改变窗体⼤⼩
  • move() 只移动位置 x()、y() 分别返回部件的位置坐标的x、y值,它们的默认值为0
  • width()、height() 返回窗体的⻓度和宽度
  • show()
  • close()
  • hide()
  • showMaximized(); //显示窗⼝最⼤化图标
  • setwindowIcon(QIcon( " : / rabbit.ico" )); //给窗体左上⻆设置⼀个图标
  • setWindowFlags() 设置窗体右上⻆的最⼩化,最⼤化,关闭按钮是否显示与 可⽤。
窗⼝如果继承QDialog,那窗⼝就只有关闭按钮;如果继承QWidget就有关闭,最⼤化,最⼩化三
个按钮,
如果要设置窗⼝中这三个按钮是否显示可以调⽤:void setWindowFlags ( Qt::WindowFlagstype )
参数为:
Qt::FrameWindowHint://没有边框的窗⼝
Qt::WindowStaysOnTopHint://总在最上⾯的窗⼝
Qt::CustomizeWindowHint://⾃定义窗⼝标题栏,以下标志必须与这个标志⼀起使⽤才有效,否则窗⼝将有默认的标题栏
Qt::WindowTitleHint://显示窗⼝标题栏
Qt::WindowSystemMenuHint://显示系统菜单
Qt::WindowMinimizeButtonHint://显示最⼩化按钮
Qt::WindowMaximizeButtonHint://显示最⼤化按钮
Qt::WindowMinMaxButtonsHint://显示最⼩化按钮和最⼤化按钮
Qt::WindowCloseButtonHint://显示关闭按钮 (取消最⼤化按钮)
//取消最⼩化按钮
this->setWindowFlags(Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint);
//取消最⼤化按钮
this->setWindowFlags(Qt::WindowMinimizeButtonHint|Qt::WindowCloseButtonHint);

//只保留关闭按钮
this->setWindowFlags(Qt::WindowCloseButtonHint);

2.1 设置窗⼝标题

调⽤窗⼝⽗类中的⽅法:setWindowTitle(tr(“Main Window”));

设置窗⼝的最⼤化,最⼩化和关闭按钮

窗⼝如果继承QDialog,那窗⼝就只有关闭按钮;如果继承QWidget就有关闭,最⼤化,最⼩化三个按钮, 如果要设置窗⼝中这三个按钮是否显示可以调⽤:void setWindowFlags ( Qt::WindowFlags type )

参数为:

Qt::FramelessWindowHint://没有边框的窗⼝

Qt::WindowStaysOnTopHint://总在最上⾯的窗⼝

Qt::CustomizeWindowHint://⾃定义窗⼝标题栏,以下标志必须与这个标志⼀起使⽤才有效,否则窗⼝将 有默认的标题栏

Qt::WindowTitleHint://显示窗⼝标题栏

Qt::WindowSystemMenuHint://显示系统菜单

Qt::WindowMinimizeButtonHint://显示最⼩化按钮

Qt::WindowMaximizeButtonHint://显示最⼤化按钮

Qt::WindowMinMaxButtonsHint://显示最⼩化按钮和最⼤化按钮

Qt::WindowCloseButtonHint://显示关闭按钮 (取消最⼤化按钮)

//只保留关闭按钮
this->setWindowFlags(Qt::WindowCloseButtonHint);

2.2 窗体的⼏何布局

对于⼀个窗⼝,往往要设置它的⼤⼩和运⾏时出现的位置,这就是本⼩节要说的 窗⼝⼏何布局。

注意:Qt中的⼏何坐标以左上⻆为原点,其中的GUI组件以左上⻆进⾏定位。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oNRbkuXv-1673330864746)(picture\27.png)]

这⾥的函数分为两类,⼀类是包含框架的,另⼀类是不包含框架的:

  • 包含框架:x()、y()、frameGeometry()、pos()和 move() 等函数;
  • 不包含框架:geometry()、width()、height()、rect()和 size() 等函数。

x()、y() 分别返回部件的位置坐标的x、y值,它们的默认值为0。⽽ geometry() 和 frameGeometry() 函数分别返回没有边框和包含边框的窗⼝框架矩形的值,其 返回值是 QRect 类型的,就是⼀个矩形,它的形式是(x,y,宽,髙)

例⼦:窗⼝⼤⼩及显示位置

#include "mainwindow.h"
//#include <QApplication>
#include<QtWidgets>
#include<QLabel>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("This is a fst UI"); //设置窗⼝标题
    //w.setGeometry(0,0,400,300); //设置控件的坐标,四个参数分别代表(X坐标,Y坐标,控件宽,控件⾼)。
    w.move(40,50);
    w.resize(300,400);
    
    QLabel label(&w); //设置⽗类为w
    //设置控件的坐标
    label.setGeometry(100,100,100,40); //四个参数分别代表(X坐标,Y坐标,控件宽,控件⾼)。
    label.setText("This is a QLabel");
    
    //label.resize(50,20); 改变部件的⼤⼩
    w.show(); //在屏幕上显示出来
    return a.exec();
}

2.3 设置菜单栏

⼀个主窗⼝最多只有⼀个菜单栏,位于主窗⼝顶部、 主窗⼝标题栏下⾯。 Qt添加菜单有两种⽅法,⼀是⽤代码直接⼿动添加,⼆是在Qtdesigner界⾯上直接添加。

1)⽤代码创建菜单

⽤代码设计菜单需要⽤到两个类QMenu和QAction。

创建主窗⼝中的菜单栏需要⽤到QMenuBar类,它是存放菜单的地⽅,相当于⼀个 容器,菜单QMenu是容器中的其中⼀项。

  • 创建菜单栏

QMenuBar *menuBr = menuBar(); //获取主窗⼝菜单栏指针

setMenuBar(menuBr);

  • 创建菜单, 调⽤ QMenu 的成员函数 addMenu 来添加菜单

QMenu是主窗⼝的⼀个菜单项及其⼦菜单,可以使⽤下边两个函数实现菜单的 创建。

QMenu* addMenu(const QString & title) ;

QMenu(const QString & title, QWidget * parent = 0)

QMenu* addMenu(const QIcon & icon, const QString & title)

  • 创建菜单项, 调⽤ QMenu 的成员函数 addAction 来添加菜单项

QAction: ⼦菜单项

QAction *pOpen = pFile->addAction(“open file”);

QAction *addAction(const QString & text);//创建⼦菜单后再添加到菜单栏

#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    
    //创建菜单栏
    QMenuBar* menuBar = new QMenuBar();
    this->setMenuBar(menuBar);
    //创建菜单项"⽂件”及其下边的⼦菜单
    QMenu* menu1=new QMenu("⽂件");
    // QMenu *menu1 = menuBar->addMenu("File");
    menu1->addAction("编辑");
    menu1->addAction("查看");
    menu1->addAction("选项");
    
    //创建菜单项"编辑”及其下边的⼦菜单
    QMenu* menu2=new QMenu("编辑");
    menu2->addAction("查找");
    menu2->addAction("复制1");
    menu2->addAction("替换");
    // 和上述等价menu2->addAction("替换");
    //QAction* pp= new QAction("2替换",menu2);
    // pp->setShortcut(Qt::CTRL | Qt::Key_A );//设置快捷⽅式CTRL+A
    // menu2->addAction(pp);
    //给菜单栏添加菜单
    menuBar->addMenu(menu1);
    menuBar->addMenu(menu2);
}
⼩结:先创建并设置菜单栏>>构造菜单项>>构造⼦菜单>>将菜单项添加到菜单栏中
    QMenu *menu1 = menuBar->addMenu("File");等价于以下两句
    QMenu* menu1=new QMenu("⽂件");
    menuBar->addMenu(menu1);

	//在主窗⼝主创建⼀个菜单栏
    QMenuBar *bar=new QMenuBar(this);
    this->setMenuBar(bar);

    //创建两个主菜单项
    QMenu* file = new QMenu("⽂件");
    QMenu* help = new QMenu("帮助");

    file->setFixedWidth(200); //设置菜单宽度
    bar->addMenu(file);
    bar->addMenu(help);

    //分布为两个主菜单添加⼦菜单项
    QMenu* file_open = new QMenu("打开",file);
    file_open->setIcon(QIcon("D:\\qt_test\\untitled18\\workspace_logo.ico"));
    file_open->addAction("打开1");
    file_open->addAction("打开2");
    file->addMenu(file_open); //将⼦菜单添加到指定主菜单下

    QMenu* file_exit = new QMenu("退出",file);
    file_exit->addAction("dsdf");
    file->addMenu(file_exit);

2)⽤Qtdesigner创建菜单

可以利⽤qt creator是⼀个集成开发⼯具,通过它不需要编写代码,就可以实现菜 单栏的功能,具体步骤如下:

1、双击mainwindow.ui⽂件,进⼊设计模式

2、在主窗体的左上⻆“在这⾥输⼊”修改为“File(&F)”,然后按下回⻋

注意:这⾥的&F表示将菜单设计成了ALT+F的快捷键,&符号在实际中是隐藏不显示的。

3、添加⼦菜单,继续在FILE下的“在这⾥输⼊”继续添加⼦菜单项,添加完成按回⻋

如果要添加⼆级⼦菜单,点击⼦菜单中的+号即可。

注意:如果在输⼊财档项内容时,⽆法输⼊中⽂,可以将中⽂在其他地⽅写好, 复制过来进⾏粘贴即可。

1)如何给⼦菜单上添加菜单图⽚哪,使其更美观哪?

QT中⼀个⼦菜单被看成⼀个Action,可以通过Action编辑器看到下边添加的菜单

双击要添加图标的某个项,弹出如下界⾯,点击图标后的按钮,选择⽂件中你提 前准备的ico图⽚。其中在shortcut项⽤来设置快捷键,可以在键盘上⽐如按下 ctrl+z等。

在加载图⽚时,可以选择从本地磁盘上加载图⽚,也可以选择从资源⽂件中加载。

2)给菜单添加槽函数

菜单QACTION组件的常⽤信号为triggered,当⽤户点击或按快捷键时会发⽣该信号。

//----在窗体类中添加如下两个槽函数
// 菜单open响应函数
void MainWindow::on_actionOPEN_triggered()
{
	ui->label->setText("你点击的是打开菜单") ;
}
//响应save点击
void MainWindow::on_actionSAVE_triggered()
{
	ui->label->setText("你点击的是保存按钮") ;
}
//---如果⾃定义槽函数
//1、头⽂件声明槽函数
private slots:
void mysave_pro();
void myopen_pro();
//2、在窗体类的构造函数㕜建⽴连接
connect( ui->actionOPEN,&QAction::triggered,this,&MainWindow::myopen_pro);
connect( ui->actionSAVE,&QAction::triggered,this,&MainWindow::mysave_pro);
//3、实现槽函数
void MainWindow::myopen_pro()
{
	ui->label->setText("你点击的是打开菜单") ;
}
void MainWindow::mysave_pro()
{
	ui->label->setText("你点击的是保存按钮") ;
}

4)QT资源⽂件简介

Qt 资源系统是⼀个跨平台的资源机制,⽤于将程序运⾏时所需要的资源以⼆进制 的形式存储于可执⾏⽂件内部。如果你的程序需要加载特定的资源(图标、⽂本 翻译等),可以将其放置在资源⽂件中,就再也不需要担⼼这些⽂件的丢失。也 就是说,如果你将资源以资源⽂件形式存储,它会被编译到可执⾏⽂件内部。

如何创建资源⽂件哪?

1、在⼯程名上点击右键,选择“添加新⽂件”,以在 Qt 分类下找到“Qt 资源⽂件”:

添加前缀(相当于增加⼀个资源⽬录),然后添加⽂件,对于添加的⽂件可以起⼀个 别名(起别名后,以后如果改了源⽂件名,不会影响到其他⽂件的使⽤)。edit_ico 就是ic_delete.png⽂件的别名。

打开资源⽂件如下图所示: qrc⽂件内部包含了图标的相对路径;rcc是Qt的资源编译器,它以qrc⽂件为编译 对象,编译产⽣了开发过程中能够直接使⽤的⽬标对象。

可以在⼯程的构建⽬录中看到已经将添加的资源⽂件变成了⼀个C++⽂件,其中⾥边就有添加的两个图⽚的⼆进制数据。

如果要再次打开资源⽂件再添加资源,可以选择open in Editor

5)⼯具栏设计

软件使⽤时所需要的⼀些⼯具,如新建、保存当前数据等。主要使⽤QToolBar、 QAction创建及使⽤⼯具栏。

MainWindow::initTool()
{
    QToolBar *tool = new QToolBar(this);
    this->addToolBar(tool);//构建⼯具栏
    QAction *tool1 = new QAction("新建");//构建⼯具栏选项
    QAction *tool2 = new QAction("打开");
    QAction *tool3 = new QAction("保存");
    QAction *tool4 = new QAction("退出");
    tool->addAction(tool1);//将⼯具栏选项添加到⼯具栏
    tool->addAction(tool2);
    tool->addAction(tool3);
    tool->addAction(tool4);
}
定义响应函数和⼦菜单⼀样。,可以把上例建的菜单拖⼊直接拖进去。

6)状态栏

状态栏⽤于输出软件的简要信息, ⼀般位于窗⼝最底部, 它的消息类型主要有实时信息,永久信 息, 进度信息等。 QStatusBar 继承⾃ QWidget。

状态栏可以显示3种类型的信息:

1.临时信息;

void QStatusBar::showMessage(const QString &message, int timeout = 0);

注意:参数中timeout的时间单位为ms。

2.正常信息:

正常信息往往是要通过⼀个控件(QLabel)来显示,并把控件设置到状态栏;

void QStatusBar::addWidget(QWidget *widget, int stretch = 0);

3.永久信息;

往往显示在状态栏的最右边,永久信息不会被临时信息覆盖隐藏,往往也是 要通过⼀个控件(QLabel)来显示,并把控件设置到状态栏。

void QStatusBar::addPermanentWidget(QWidget *widget, int stretch = 0

//statusBar() 创建并返回⼀个空的状态栏,是QMainWindow类中的⼀个⽅法。
statusBar()->addWidget(new QLabel(" label1"));
statusBar()->addWidget(new QLabel("label2"));
statusBar()->addPermanentWidget(new QLabel("label3"));
statusBar()->addPermanentWidget(new QLabel("label4"));
statusBar()->showMessage("留⾔", 5000);
statusBar()->setSizeGripEnabled(false); //不显示右下⻆拖放控制点
三、对话框窗⼝设计

3.1 对话框简介

对话框主要⽤来和⽤户进⾏简短交互的顶层窗⼝, QDialog是Qt中所有对话框窗⼝的基类

QDialog继承于QWidget是⼀种容器类型的组件 ,QDialog作为⼀种专⽤的交互窗 ⼝⽽存在 ,QDialog不能作为⼦部件嵌⼊其它容器中 。

对话框主要分为两类:

类型:模态对话框 显示:exec

​ ⾮模态对话框 显示:show();

**模态对话框:**当它弹出后,本应⽤程序其余窗⼝将再也不接受⽤户输⼊,只有该对话框响应⽤户输⼊,在对它进 ⾏相应操做退出后,其余窗⼝才能继续与⽤户交 互。在模态对话框中,exec有⾃⼰的消息循环;并且把app的消息循环接管了;也 就是当显示该对话框的时候不能去点击其它窗⼝部件;如果Dialog通过exec来显 示,那么可以通过accept或者reject来关闭窗⼝。(⽐如word中的“另存为”)。

注意:只有模态对话框才有返回值的概念,模态对话框的返回值⽤于表示交互结 果 。

QDialog的返回值标准只有两个:

QDialog返回值

ConstantValue
QDialog::Accepted1
QDialog::Rejected0

调⽤void QDialog::done ( int r )函数指定exec的返回值;

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QDialog>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QDialog dialog(this);
    QLabel* lb1 =new QLabel("kkkk",&dialog); //向对话框中添加内容
    dialog.exec();
    //QDialog *dialog =new QDialog(this);
    //dialog->exec();
}

//当我们在使⽤QDialog的窗⼝时,需要点击确定或者取消按钮,关闭该窗⼝且通知使⽤者
//获取返回值
QTestDialog dlg;
int nResult = dlg.exec();
if(nResult == QDialog::Accepted) //点击了确定按钮
{
	//代码实际处理
}
else
{
	//代码实际处理
}
或者⽤done(Accepted); //确定
done(Rejected); //取消

⾮模态对话框:对话框弹出后,本程序其余窗⼝仍能响应⽤户输⼊(显示后独⽴存在但可以同时与⽗窗⼝进⾏交互),是⼀种⾮阻塞式的对话框调⽤⽅式。 ⾮模态对话框通常⽤来显示提示信息等(⽐如word中的“查找与替换)。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QDialog>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QDialog *dialog =new QDialog(this); //在构造⽅法中创建⼀个⾮模态对话框
    dialog->show();
}

要想使⼀个对话框成为⼀个模态对话框,⽤.exec()函数调⽤;要想成为⾮模态对话框,⽤new建⽴,⽤.show()函数调⽤。对 象.show()与.exec()的不⼀样:调⽤完show后控制权交给调⽤者,程序继续 往下进⾏,⽽exec只有当对话框关闭时才能返回。

3.2 标准对话框

Qt 为应⽤程序设计提供了⼀些常⽤的标准对话框,如打开⽂件对话框、选择颜⾊对话框、信息提示和确认选择对话框、标准输⼊对话框等,⽤户⽆需再⾃⼰设计这些常⽤的对话框,这样可以减少程序设计⼯作量。

1.系统对话框

​ 1.1 ⽂件对话框(QFileDialog)

​ 常⽤静态函数:

​ 1.1.1 QString QFileDialog::getExistingDirectory() 打开⼀个⽬录

​ 1.1.2 QString QFileDialog::getOpenFileName() 启动⼀个打开⽂件对话 框

​ 1.1.3 QStringList QFileDialog::getOpenFileNames() 启动⼀个打开多个⽂ 件对话框

​ 1.1.4 QString QFileDialog::getSaveFileName() 启动⼀个另存为对话框

​ 1.2 颜⾊对话框(QColorDialog)

​ QColor QColorDialog::getColor()

​ 1.3 字体对话框(QFontDialog)

​ QFont QFontDialog::getfont()

2.消息对话框(QMessageBox) ,

QMessageBox::question

QMessageBox::about

QMessageBox::aboutQt

QMessageBox::critical

QMessageBox::information

QMessageBox::warnning

警告对话框的warning() 函数原型是:

StandardButton QMessageBox::warning(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton)

parent: 是对话框的⽗窗⼝,指定⽗窗⼝之后,打开对话框时,对话框将⾃动显示在⽗窗⼝的上 ⽅中间位置;

title 是对话框标题字符串;

text 是对话框需要显示的信息字符串;

buttons 是对话框提供的按钮,缺省只有⼀个 OK 按钮;

StandardButton 是各种按钮的定义,如 OK、Yes、No、Cancel 等,其枚举取值是 QMessageBox::Ok、QMessageBox::Cancel、QMessageBox::Close 等。

defaultButton 是缺省选择的按钮,缺省表示没有选择

3.标准输⼊对话框(QInputDialog)

QInputDialog::gettext

QInputDialog::getint

QInputDialog::getdouble

QInputDialog::getitem

利⽤图形化设计⼯具,直接选择按钮转到槽进⾏设计。

// -----------------------头⽂件定义对话框对象 声明槽函数
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFileDialog>
#include <QFontDialog>
#include <QColorDialog>
#include<QMessageBox>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
	Q_OBJECT
    
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    QFileDialog *dhk;
    QFontDialog *myfont;
    QColorDialog *mycolor;
    QMessageBox *mydialog;
    
private slots:
    //void on_btn_open_file_clicked();
    void on_btn_file_clicked();
    void on_btn_dir_clicked();
    void on_btn_save_file_clicked();
    void on_btn_select_color_clicked();
    void on_btn_font_clicked();
    void on_btn_warning_clicked();
    void on_btn_information_clicked();
    void on_btn_information_2_clicked();
    
private:
	Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

//------------------------cpp中实现的槽函数
void MainWindow::on_btn_file_clicked()
{
    QString str2=dhk->getOpenFileName();
    ui->label->setText(str2);
}
void MainWindow::on_btn_dir_clicked()
{
    QString str1=dhk->getExistingDirectory(); //打开⽬录对话框,返回当前路径字符串
    ui->label->setText(str1);
}
void MainWindow::on_btn_save_file_clicked()
{
    QString str1=dhk->getSaveFileName();
    ui->label->setText(str1);
}
void MainWindow::on_btn_select_color_clicked()
{
	qDebug()<<mycolor->getColor()<<endl; //打印颜⾊对象
}
void MainWindow::on_btn_font_clicked()
{
    bool ok;
    //.family()返回字体类型名称
    QString str1=myfont->getFont(&ok).toString(); //设置字体,并打印选择的字体,返回字体类型,⼤⼩
    ui->label->setText(str1);
    qDebug()<<ok<<endl;
}
void MainWindow::on_btn_warning_clicked()
{
	mydialog->warning(this,"jinggao","adv");
}
void MainWindow::on_btn_information_clicked()
{
	mydialog->information(this,"中国","cesdsfsdfsdffs");
}
void MainWindow::on_btn_information_2_clicked()
{
	int a=mydialog->question(this,"中国1","1cesdsfsdfsdffs");
    if(a==QMessageBox::Yes) //yes是QMessageBox类中的枚举常量
    	qDebug()<<"yes"<<endl;
    else
    	qDebug()<<"no"<<endl;
}

另存为的其他设置:

QString str1=dhk->getSaveFileName();

  • 它的四个参数的作⽤分别是:指定⽗窗⼝、设置对话框标题、指定默认打开的⽬录路径和设 置⽂件类型的过滤器。
  • 如果不指定⽂件过滤器,则默认选择所有类型的⽂件。
  • 注意:代码中 *png 和 *jpg 之间需要⼀个空格。
  • 可以设置不同类型的过滤器,不同类型间⽤两个分号 “;;”隔开。
四、QT的多界⾯编程

在Qt编程中经常遇到多个界⾯之间的切换, ⽐如从登录界⾯跳转到主界⾯, 主界 ⾯跳转到设置界⾯,在返回到主界⾯等待场合。

窗体中的close和hide成员函数的区别是:hide成员函数(该函数等同于 setVisible(false))只是隐藏窗体,不会发送任何信号。

close⼀般也是隐藏窗⼝。但是它会发送QCloseEvent事件。你可以重写void QWidget::closeEvent(QCloseEvent * event) [virtual protected],可以隐藏 widget或者不隐藏。

对⼀个窗体如果调⽤close函数后,如果再调⽤show(),这个窗体⼜会被显示出 来。

2、Qt全屏显示函数

(1).window.showFullScreen()//此⽅法只对顶级窗⼝有效,对⼦窗⼝⽆效

(2).yourwidget->setWindowFlags(Qt::window | Qt::FramelessWindowHint);

(第⼀个Qt::window表示此widget是窗⼝类型,第⼆个参数使⽤⽆框架就是没有标题,状态 栏和边框)

Qt最⼤化显示函数: window.showMaximized()

Qt最⼩化显示函数 : window.showMinimized()

Qt固定尺⼨显示函数: window.resize(x,y)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3CEJAH1l-1673330864747)(picture\35.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KLDBzXr4-1673330864747)(picture\36.png)]

mainwindow.cpp窗体源码:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "form.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
	ui->setupUi(this);
}
MainWindow::~MainWindow()
{
	delete ui;
}
void MainWindow::on_pushButton_2_clicked()
{
	this->close();
}
void MainWindow::on_pushButton_clicked()
{
    Form *mywin=new Form ;
    mywin->show();
    this->close();
}

⼦窗体from.cpp窗体源码:

#include "form.h"
#include "ui_form.h"
#include "mainwindow.h"
Form::Form(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Form)
{
	ui->setupUi(this);
}
Form::~Form()
{
	delete ui;
}
void Form::on_pushButton_clicked()
{
    this->close();
    MainWindow *mylogin=new MainWindow;
    mylogin->show();
}

06QT的事件处理

⼀、事件简介

QT程序是事件驱动的, 程序的每个动作都是由内部某个事件所触发。QT事件的发⽣和处理成为程序运⾏的主线,存在于程序整个⽣命周期。

1)事件定义

事件(event)是由系统或者 Qt 本身在不同的时刻发出的。当⽤户按下⿏标、敲下键盘,或者是窗⼝需要重新绘制的时候,都会发出⼀个相应的事件。⼀些事件在对⽤户操作做出响应时发出,如键盘事件等;另⼀些事件则是由系统⾃动发出,如计时器事件。

Qt 程序需要在main()函数创建⼀个QCoreApplication对象,然后调⽤它的exec()函数。这个函数就是开始 Qt 的事件循环。在执⾏exec()函数之后,程序将进⼊事件循环来监听应⽤程序的事件。

2)事件与信号

Qt 中的事件和信号槽却并不是可以相互替代的。信号由具体的对象发出,然后会⻢上交给由connect()函数连接的槽进⾏处理;⽽对于事件,Qt 使⽤⼀个事件队列对所有发出的事件进⾏维护,当新的事件产⽣时,会被追加到事件队列的尾部。

前⼀个事件完成后,取出后⾯的事件进⾏处理。但是,必要的时候,Qt 的事件也可以不进⼊事件队列,⽽是直接处理。信号⼀旦发出,对应的槽函数⼀定会被执⾏。但是,事件则可以使⽤“事件过滤器”进⾏过滤,对于有些事件进⾏额外的处理,另外的事件则不关⼼。

事件与信号的区别?

● 信号是由对象产⽣的,⽽事件则不⼀定是由对象产⽣的(⽐如由⿏标产⽣的事

件),事件通常来⾃底层的窗⼝系统,但也可以⼿动发送⾃定义的事件,可⻅

信号和事件的来源是不同的。

● 事件既可以同步使⽤,也可以异步使⽤ (取决于调⽤sendEvent()还是

postEvents()),⽽使⽤信号和槽总是同步的,事件的另⼀个好处是可以被过

滤。

3)事件的分类

在Qt中,事件被封装成⼀个个对象,所有的事件均继承⾃抽象类QEvent,.常⻅的有键盘事件keyPressEvent,keyReleaseEvent,mousePressEvent,mouseReleaseEvent,timerEvent等,其中键盘和⿏标相关事件来⾃于底层的操作系统,它们以异步的形式通知Qt事件处理系统。与QEvent类的继承关系如下图所示:

根据事件的来源和传递⽅式,事件可分为以下三⼤类:

⾃发事件:这是由窗⼝系统⽣成的,这些事件置于系统队列中,并由事件循环⼀个接⼀个地处理。

发布的事件(Posted events):该类事件由Qt或应⽤程序⽣成,这些事件由Qt排队,并由事件循环处理。

发送的事件(Sent events):该类事件由Qt或应⽤程序⽣成,这些事件直接发送到⽬标对象,不经过事件循环处理。

4)事件的处理

QEvent及其⼦类虽然可以描述⼀个事件,但并不对事件进⾏处理。Qt为绝⼤多数常⽤类型的事件提供了默认的事件处理函数,并作了默认处理,这些事件处理函数位于QObject的⼦类中,⽐如QWidget::mousePressEvent()函数⽤于处理⿏标按下事件,QWidget::keyPressEvent()⽤于处理键盘按下事件等。对这些默认事件处理函数的调⽤是通过QObject::event()虚函数进⾏的,因此若默认的事件处理函数不能满⾜⽤户要求(⽐如对Tab键的处理),则可以通过重新实现event()函数来达到⽬的。

处理事件的常⽤⽅法为:

1)重写控件的事件处理函数:如重写keyPressEvent(),mousePressEvent()和 paintEvent(),这是最常⽤的事件处理⽅法,不过只能⽤来出来特定部件的特定事件。

2)给QApplication安装事件过滤器,使⽤过滤器可以在⼀个界⾯类中 同时处理不同的⼦部件。

3)重新实现event函数,QObject类的event()函数可以在事件到达默认的事件处理函数前获得该事件。

5)事件的传递

当事件发⽣时,Qt 将创建⼀个事件对象。Qt 中所有事件类都继承于QEvent。在事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。event() 函数并不直接处理事件,⽽是按照事件对象的类型分派给特定的事件处理函数(event handler)。

绝⼤部分事件类型都由特定的类来表示,⽐如常⻅的QResizeEvent、QPaintEvent、QMouseEvent、QKeyEvent、QCloseEvent等。每⼀个具体的事 件类都是从QEvent派⽣下来的,并添加了与该事件相关的函数。例如,QResizeEvent添加了size()和oldSize() 函数,以使控件知道它的尺⼨发⽣了怎样的变化。并且,有些事件类不⽌表示⼀种事件,⽐如QMouseEvent,可以表示⿏标按下,⿏标双击,⿏标移动,以及其他相关操作。

每⼀种事件都有⼀个相关的类型,由QEvent::Type定义。这可以帮助我们在程序运⾏时确定当前的事件对象具体是由哪⼀个事件类构造出来的。

常⽤的事件的相关类型有:

● QEvent::MouseButtonPress - ⿏标按下,QMouseEvent。

● QEvent::MouseButtonRelease - ⿏标抬起,QMouseEvent。

● QEvent::MouseButtonDblClick - ⿏标再次按下,ahref=“qmouseevent.html”>QMouseEvent。

● QEvent::MouseMove - ⿏标移动,QMouseEvent。

● QEvent::IMStart - 输⼊法写作开始。

● QEvent::IMCompose - 发⽣输⼊法写作。

● QEvent::IMEnd - 输⼊法写作结束。

● QEvent::KeyPress - 键按下(举例,包括Shift)QKeyEvent。

● QEvent::KeyRelease - 键抬起,QKeyEvent。

● QEvent::Timer - 规则的定时器事件,QTimerEvent。

● QEvent::Show - 窗⼝部件被显示到屏幕上,QShowEvent。

● QEvent::Hide - 窗⼝部件被隐藏,QHideEvent。

● QEvent::ShowToParent - ⼀个⼦窗⼝部件被显示。

● QEvent::HideToParent - ⼀个⼦窗⼝部件被隐藏。

● QEvent::FocusIn - 窗⼝部件获得键盘焦点,QFocusEvent。

● QEvent::FocusOut - 窗⼝部件失去键盘焦点,QFocusEvent。

● QEvent::Close - 窗⼝部件被关闭(永久性地) QCloseEvent。

● QEvent::User - ⽤户定义事件。

7)键盘事件

我们在做软件时候,经常会碰到这样的场景,⽐如按下F5进⾏刷新功能,按下F1进⾏帮助之类的快捷键⽅式。那么在QT中该怎样做呢?

QKeyEvent类⽤来描述⼀个键盘事件。当键盘按键被按下或者被释放时,键盘事件便会被发送给拥有键盘输⼈焦点的部件。

QKeyEvent的key()函数可以获取具体的按键,对于Qt中给定的所有按键,可以在帮助中查看Qt: :Key关键字。需要特别说明的是,回⻋键在这⾥是

**Qt::Key_Return;键盘上的⼀些修饰键,⽐如Ctrl和Shift等, 这⾥需要使⽤QKeyEvent的 modifiers()函数来获取,**可以在帮助中使⽤Qt:: KeyboardModifier关键字来査看所有的修饰键。

我们如果想捕获某种类型的事件并进⾏⾃定义处理,那么只需要实现重写这些事件处理器就可以,Qt中针对每⼀种常⻅的事件类型都提供了相应的事件处理器⽐

如键盘事件QKeyEvent有两个键盘事件成员函数:

*void QWidget::keyPressEvent(QKeyEvent event) //键盘按下事件,键盘按下事件处理器

*void QWidget::keyReleaseEvent(QKeyEvent event) //键盘松开事件键盘松开事件处理器

1)如何使⽤按键事件

在控件的头⽂件.h中进⾏声明:

void keyPressEvent(QKeyEvent *event); //键盘按下事件 
void keyReleaseEvent(QKeyEvent *event); //键盘松开事件

2)在cpp中进⾏实现函数的功能

//按下则使窗⼝最⼤化this->setWindowState(Qt::WindowMaximized);

//keyPressEvent是QWidget⾥⾯的函数,所以凡是继承⾃QWidget的类都可以通过实现这个函数来完成对按键事件的响应

//实现keyPressEvent 
void MainWindow::keyPressEvent(QKeyEvent *ev) //重写事件处理器 
{ 
    ui->label->clear(); 
    if(ev->key() == Qt::Key_F5) 
    { 
        ui->label->setText("F5被按下了"); 
        return; 
    }else if(ev->key() == Qt::Key_F6) 
        ui->label->setText("F6被按下了"); 
    
    QWidget::keyPressEvent(ev); 
}
//如果是不想让别的窗体获得,在函数⾥直接return。如果需要其他的窗体获取, QWidget::keyPressEvent(ev); 
//必须是 QWidget的⼦类 这个函数保证了即使窗⼝没获得焦点的情况下也能捕获到按键事件 grabKeyboard()

8)⿏标事件

QMouseEvent类⽤来表示⼀个⿏标事件,在窗⼝部件中按下⿏标或移动⿏标指针时,都会产⽣⿏标事件。利⽤QMouseEvent类可以获取⿏标哪个按键被按下了,⿏标的当前位置等信息。通常是重定义部件的⿏标事件处理函数来进⾏⼀些⾃定义操作。Qt中的QMouseEvent⼀般只涉及⿏标左键或右键的单击、释放等操作,⽽对⿏标滚轮的响应则通过QWheeEvent来处理,通过该类可以获取⿏标滚轮移动的⽅向和距离。

可以通过函数pos()、x()、y()得知⿏标事件发⽣时⿏标指针相对于窗⼝的位置。可以使⽤QWidget::setEndabled()来开启/关闭对应的窗⼝是否接受键盘和⿏标事件。

需要对⿏标事件进⾏处理时,通常要重新实现以下⼏个⿏标事件处理函数:

QWidget::mousePressEvent()

QWidget::mouseReleaseEvent()

QWidget::mouseDoubleClickEvent()

QWidget::mouseMoveEvent()

QMouseEvent中保存了两个坐标,⼀个是全局坐标,当然另外⼀个是局部坐标。

全局坐标(globalPos())即是桌⾯屏幕坐标(screen coordinates),这个跟windows下的调⽤getCursorPos函数得到的结果⼀致。局部坐标(pos())即是相对当前active widget的坐标,左上⻆坐标为(0, 0)

头⽂件

#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(); 
private slots: 
    //void on_pushButton_clicked(); 
protected: 
    void mousePressEvent(QMouseEvent *e) ; 
    void mouseReleaseEvent(QMouseEvent *e) ; 
    void mouseDoubleClickEvent(QMouseEvent *e) ; 
    void mouseMoveEvent(QMouseEvent *e); 
    void wheelEvent(QWheelEvent *e); 
private:
    Ui::Widget *ui; 
    QPoint offset; 
};#endif // WIDGET_H

cpp⽂件

#include "widget.h" 
#include "ui_widget.h" 
#include<QMouseEvent> 
#include<QDebug> 
Widget::Widget(QWidget *parent) 
    : QWidget(parent) 
    , ui(new Ui::Widget) 
{ 
        ui->setupUi(this); 
        QCursor cursor; 
        cursor.setShape(Qt::OpenHandCursor); 
        setCursor(cursor); 
}

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

//测试⿏标的左键与右键 
void Widget::mousePressEvent(QMouseEvent *e) 
{ 
    if(e->button()== Qt::LeftButton) //⿏标按下时先判断是哪⼀个键被按下了 
    { 
        QCursor cursor; 
        cursor.setShape(Qt::ClosedHandCursor); 
        setCursor(cursor); 
        QApplication::setOverrideCursor(cursor); 
        offset=e->globalPos()-pos(); //pos()获取⿏标在窗⼝中的位置 
    }
    else if(e->button()== Qt::RightButton) 
    { 
        QCursor cursor(QPixmap("d:\\qq.png")); 		
        QApplication::setOverrideCursor(cursor); 
    } 
}
//测试⿏标的释放时间 
void Widget::mouseReleaseEvent(QMouseEvent *e) 
{ 
    Q_UNUSED(e); //Q_UNUSED() 没有实质性的作⽤,⽤来避免编译器警告⽐如e变量未使⽤ 
    QApplication::restoreOverrideCursor(); }
void Widget::mouseDoubleClickEvent(QMouseEvent *e) 
{ 
    if(e->button()== Qt::LeftButton) //⿏标按下时先判断是哪⼀个键被按下了 
    {
        if(windowState()!=Qt::WindowFullScreen) 
            setWindowState(Qt::WindowFullScreen) ; //this- >showWindowFullScreen() 
        else
            setWindowState(Qt::WindowNoState);//恢复窗⼝以前⼤⼩ 
    } 
}
void Widget::mouseMoveEvent(QMouseEvent *e) 
{ 
    QPoint temp; 
    if(e->buttons()&Qt::LeftButton) 
    { 
        temp=e->globalPos()-offset; //globalPos()获取⿏标指针的位置 
        move(temp); //move的原点是⽗窗⼝的左上⻆,这⾥的move移动的是窗体对象 
    }
    //实时打印⿏标的坐标 
    qDebug()<<"("<<e->x()<<" "<<e->y()<<")"<<temp.x()<<"-"<<e->globalX() <<endl; 
}
void Widget::wheelEvent(QWheelEvent *e) 
{ 
    if(e->delta()>0)//QWheelEvent类中的delta()⽅法⽤于获取滚轮的距离 
        ui->textEdit->zoomIn(); 
    else
        ui->textEdit->zoomOut(); 
}

⿏标与按键组合 实现⼀些控制的案例

void MainWindow::wheelEvent(QWheelEvent *e) 
{ 
    if(QApplication::keyboardModifiers() == Qt::ControlModifier) 
    { 
        if(e->delta()>0)//QWheelEvent类中的delta()⽅法⽤于获取滚轮的距离 
        { 
            ui->textEdit->zoomIn(); 
        }
        else 
        { 
            ui->textEdit->zoomOut(); 
        } 
    }
}

9)时间事件

QTimerEvent 类⽤来描述⼀个定时器事件。对于⼀个 QObject 的⼦类,只需要使⽤ int QObject::startTimer ( int interval) 函数来开启⼀个定时器,这个函数需要输⼈⼀个以毫秒为单位的整数作为参数来表明设定的时间,它返回⼀个整型编号来代表这个定时器。当定时器溢出时就可以在 timerEvent() 函数中获取该定时器的编号来进⾏相关操作。

使⽤ QTimerEvent 的 timerId() 函数来获取定时器的编号,然后判断是哪⼀个定时器并分别进⾏不同的操作。

如果要关闭定时器可以调⽤:void QObject::killTimer(int id)

功能:关闭指定id的定时器

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 
#include <QMainWindow> 
#include<QtSql> 
QT_BEGIN_NAMESPACE 
namespace Ui { class MainWindow; } 
QT_END_NAMESPACE 
    
class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 
 public: 
    MainWindow(QWidget *parent = nullptr); 
    ~MainWindow(); 
    void timerEvent(QTimerEvent *event); // 定时器事件 
    int id1,id2,id3; 
private slots: 
    void on_pushButton_clicked(); 
private: 
    Ui::MainWindow *ui; 
};#endif // MAINWINDOW_H 
    
// 定时器事件函数 
void MainWindow::timerEvent(QTimerEvent *event) 
{ 
    // 1秒钟时间到,则定时器1溢出 
    if (event->timerId() == id1) 
    { 
        qDebug()<<"timer1"; 
    }
    else if(event->timerId() == id3) 
    { 
        qDebug()<<"timer2"; 
    } 
}
MainWindow::~MainWindow() 
{ 
    delete ui; 
}
void MainWindow::on_pushButton_clicked() 
{ 
    QObject::killTimer(id1);//关闭定时器
}

10)事件过滤器

Qt中的事件过滤器是⼀个功能极其强⼤的模块。如果在部件上安装了事件过滤

器,那么,过滤器便可以先于部件捕获事件,从⽽进⾏相应的处理。

事件过滤器->部件的event函数->部件的事件处理函数

事件过滤器由QObject类中的两个函数来实现。⼀个是 installEventFilter,它负责在相应部件上安装事件过滤器,其声明为:

void QObject::installEventFilter(QObject *filterObj);

其中,filterObj参数表示要在其上实现事件过滤器函数的部件。请注意,如果我们在⼀个部件安装了事件过滤器,⼀般在其⽗控件上实现事件过滤器函数。

第⼆个函数是 eventFilter 函数,我们在此函数中实现事件过滤器。

请注意:

1)该函数在 QObject 类中声明为⼀个虚函数,因此只能由 QObject 的⼦类继承使⽤

2)该函数在 QObject 类中是⼀个保护成员,因此⼦类继承时不可以作为⼀个公有成员

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 
#include <QMainWindow> 
QT_BEGIN_NAMESPACE 
namespace Ui { class MainWindow; } 
QT_END_NAMESPACE 
    
class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 
public: 
    MainWindow(QWidget *parent = nullptr); 
    ~MainWindow(); 
    bool eventFilter(QObject *watched, QEvent *event); 
private: 
    Ui::MainWindow *ui; 
};#endif // MAINWINDOW_H 
    
#include "mainwindow.h" 
#include "ui_mainwindow.h" 
#include<QDebug> 
#include<QWheelEvent> 
MainWindow::MainWindow(QWidget *parent) 
    : QMainWindow(parent) 
    , ui(new Ui::MainWindow) 
{ 
        ui->setupUi(this); 
        ui->textEdit->installEventFilter(this); 
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event) 
{ 
    if(obj==ui->textEdit) 
    { 
        if(event->type()==QEvent::Wheel) 
        { 
            QWheelEvent * w=static_cast<QWheelEvent*>(event); 
            if(w->delta()>0) 
                ui->textEdit->zoomIn(); 
            else
                ui->textEdit->zoomOut();//向下滚动放⼤ 
            return true;
        }
        else
            return false; 
    }
    else
        return QWidget::eventFilter(obj, event); 
}
MainWindow::~MainWindow() 
{ 
    delete ui; 
}

扩展:

它反映了包括Qt在内的GUI应⽤程序的消息处理模型:

(1) ⽤户操作界⾯,被操作系统内核空间中的设备驱动程序感知

(2) 设备驱动程序向操作系统的⽤户空间的GUI应⽤程序发出系统消息

(3) GUI应⽤程序将系统消息转换为信号,进⽽触发槽函数

在GUI应⽤程序中,⼀个核⼼且关键的操作就是将系统消息转换为信号,涉及到Qt的事件处理机制:

(1) Qt平台将系统底层发来的消息转换为Qt事件,并将其Qt事件产⽣后⽴即被分发到 QWidget对象

(2) QWidget对象中的event(QEvent* )函数对事件进⾏处理,即根据不同的事件,调⽤不同的事件处理函数

(3) 在事件处理函数中发送Qt中预定义的对应事件的Qt信号,进⽽调⽤到信号关联的槽函数

下⾯将通过两个阶段,对Qt中的事件处理机制的处理流程进⾏分析,上述的问题的解答也涵盖其中。

其他

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dRppAlwX-1673330864748)(picture\38.png)]

QT将系统产⽣的消息转化为QT事件,QT事件被封装为对象,所有的QT事件均继承抽象类QEvent,⽤于描述程序内部或外部发⽣的动作,任意的QObject对象都具备处理QT事件的能⼒。

GUI应⽤程序的事件处理:

A、QT事件产⽣后会被⽴即发送到相应的QWidget对象

B、相应的QWidget中的event(QEvent *)进⾏事件处理

C、event(QEvent *)根据事件类型调⽤不同的事件处理函数

D、在事件处理函数中发送QT预定义的信号

E、调⽤信号关联的槽函数

07文件操作

⼀、⽂件输⼊与输出设备简介

⽂件操作是应⽤程序必不可少的部分。 Qt 作为⼀个通⽤开发库, 提供了跨平台的 ⽂件操作能⼒。 Qt 通过 QIODevice 提供了对 I/O 设备的抽象, 这些设备具有读 写字节块的能⼒。 下⾯是 I/O 设备的类图(Qt5) :

它可以⽤来读/写⽂本、⼆进制⽂件和Qt资源的I/O设备

QIODevice: 所有 I/O 设备类的⽗类, 提供了字节块读写的通⽤操作以及基 本接⼝;

QFileDevice: Qt5 新增加的类, 提供了有关⽂件操作的通⽤实现。

QFlie: 访问本地⽂件或者嵌⼊资源;

QTemporaryFile: 创建和访问本地⽂件系统的临时⽂件;

QBuffer: 读写 QbyteArray, 内存⽂件;

QProcess: 运⾏外部程序, 处理进程间通讯;

QAbstractSocket: 所有套接字类的⽗类;

QTcpSocket: TCP 协议⽹络数据传输;

QUdpSocket: 传输 UDP 报⽂;

QSslSocket: 使⽤ SSL/TLS 传输数据;

在打开⼀个⽂件时,需要指定其打开模式,QIODevice中所有的打开模式是由 QIODevice:: OpenMode枚举类型定义,其取值如下表所示:

QIODevice::NotOpen 未打开

QIODevice::ReadOnly 以只读⽅式打开

QIODevice::WriteOnly 以只写⽅式打开

QIODevice::ReadWrite 以读写⽅式打开

QIODevice::Append 以追加的⽅式打开,新增加的内容将被追加到⽂件末尾

QIODevice::Truncate 以重写的⽅式打开,在写⼊新的数据时会将原有数据全部清除,游标设置在⽂件开头。

QIODevice::Text 在读取时,将⾏结束符转换成 \n;在写⼊时,将⾏结束符转换 成本地格式,例如 Win32 平台上是 \r\n QIODevice::Unbuffered 忽略缓存

QIODevice区分两种类型的设备:

  • 顺序访问设备

是指它们的数据只能访问⼀遍: 从头⾛到尾, 从第⼀个字节开始访问, 直到 最后⼀个字节, 中途不能返回去读取上⼀个字节, 这其中, QProcess、 QTcpSocket、 QUdpSoctet 和 QSslSocket 是顺序访问设备。

  • 随机访问设备

可以访问任意位置任意次数, 还可以使⽤ QIODevice::seek()函数来重新定 位⽂件访问位置指针, QFile、 QTemporaryFile 和 QBuffer 是随机访问设备,

⽂件操作主要提供了3个类:QFile、QFileInfo、QDir

QT提供了两种读写纯⽂本⽂件的⽅法:

①QFile类的IODevice读写功能直接进⾏读写

②QFile和QTextStream结合起来,⽤流的⽅法进⾏⽂件读写

⼆、QFile详解

QFile 可以⽤来读/写⽂本⽂件、⼆进制⽂件和 Qt 资源的 I/0 设备,我们通常会将 ⽂件路径作为参数传给 QFile 的构造函数。 不过也可以在创建好对象最后, 使⽤ setFileName()来修改。 QFile 需要使⽤ / 作为⽂件分隔符, 不过, 它会⾃动将其 转换成操作系统所需要的形式。可以使⽤exists()来检查⽂件是否使⽤remove()来删除⼀个 ⽂件。

⼀个⽂件可以使⽤open()打开,使⽤close()关闭,使⽤flush()刷新。

1)纯⽂本⽂件内容的写⼊

QIODevice中重载的写⽅法有:

bool QIODevice::putChar(char c)

将字符 c 写⼊设备。成功时返回 true;否则返回 false。(⼀次只操作⼀个字符)

bool QIODevice::getChar(char *c)

从设备读取⼀个字符, 并将其存储在 c 中。如果 c 为 0, 则该字符将被丢弃。成功时 返回 true;否则返回 false。(⼀次只操作⼀个字符)

qint64 QIODevice::write ( const char * data, qint64 maxSize )

将最多maxSize字节的数据从数据写⼊设备。 返回实际写⼊的字节数,如果发⽣ 错误,则返回-1。

qint64 QIODevice::write ( const char * data )

将数据从零字节的8位字符串写⼊设备。 返回实际写⼊的字节数,如果发⽣错误, 则返回-1。

qint64 QIODevice::write ( const QByteArray & byteArray )

将byteArray的内容写⼊设备。 返回实际写⼊的字节数,如果发⽣错误,则返 回-1。

其他:

⽤来打开⼀个⽂件对象

bool QFile::open(OpenMode mode)

QFile file("d://a.txt");
//在访问设备之前,必须调⽤open()来设置正确的OpenMode(例如ReadOnly或ReadWrite)
if(!file.open(QIODevice::WriteOnly))//以写的⽅式打开⽂件,如果⽂件不存在则创建,
    qDebug()<<file.errorString();

//按char型数组写⼊
const char* data = "hello world111!\n";
file.write(data);

//按QByteArray写⼊字节数组
QByteArray buf = "abc";
file.write(buf); //写⼊⽂件,⽀持QByteArray和 char * 类型数据写⼊
file.close();//关闭⽂件

如果是⼀个QString对象,需要使⽤toUtf8()⽅法转换为QByteArray,

例如:

QString buf = “laowang”;

QByteArray a = buf.toUtf8(); //中⽂转字节流

2)纯⽂本⽂件读取

QIODevice涉及到的读⽅法主要有:

从设备读取最多maxSize字节为数据,并返回读取的字节数。如果发⽣错误,返 回-1

qint64 QIODevice::read ( char * data, qint64 maxSize )

从设备读取最多maxSize字节,并返回读取为QByteArray的数据。

QByteArray QIODevice::read ( qint64 maxSize )

读取⽂件所有内容,读取之后将会处于⽂件的末尾,此功能⽆法报告错误;返回⼀个 空的QByteArray()可能意味着当前没有数据可⽤于读取,或者发⽣了错误。

QByteArray QIODevice::readAll ()

此函数从设备读取⼀⾏ ASCII 字符, 最⼤最⼤最⼤⼤⼩为-1 字节, 将字符存储在数 据中, 并返回读取的字节数。如果⽆法读取⾏, 但没有错误, 则此函数返回0。如果 发⽣错误, 此函数返回可以读取的内容的⻓度, 如果未读取任何内容, 则返回-1。

qint64 QIODevice::readLine ( char * data, qint64 maxSize )

判断是否到达了⽂件的末尾(如果已达到⽂件的末尾, 则返回 true。否则返回 false。)

[virtual] bool QFileDevice::atEnd()

const 获取⽂件的⼤⼩

[virtual] qint64 QFile::size() const

定位到⽂件的任意位置

[virtual] bool QFileDevice::seek(qint64 pos)

获取当前的位置

[virtual] qint64 QFileDevice::pos() const

/*待读取的⽂件内容wi:
hello world111!
中国加油
*/
#include <QApplication>
#include<QTextCodec>
#include <QFile>
#include<QtDebug>
QFile file("d://ljs.txt");
if(!file.open(QIODevice::ReadOnly))//以读的⽅式打开⽂件
	qDebug()<<file.errorString();

QByteArray buf = file.readAll();//读取⽂件所有数据

qDebug()<<"buf: "<<buf;
//读取结果为:>>>buf: "hello
world111!\n\r\n\xD6\xD0\xB9\xFA\xBC\xD3\xD3\xCD"
file.close();//关闭⽂件

//---readAll()读取的是字节数组,遇到ASCII码原样显示,遇到⾮ASCII则默认按unicode码显示
//----改进代码如下:
if(!file.open(QIODevice::ReadOnly)) //以读的⽅式打开⽂件
	qDebug()<<file.errorString();

//使⽤ QTextCodec类需要包含#include<QTextCodec>
QTextCodec *codec = QTextCodec::codecForName("GBK");
QString buf = codec->toUnicode(file.readAll()); //读取⽂件所有数据

qDebug()<<"buf: "<<buf<<endl<<file.size()file.pos();//获取⽂件⼤⼩
//打印结果:>>>buf: "hello world111!\n\r\n中国加油" 26 26
file.close();//关闭⽂件

注意:在默认情况下,Qt 以 Unicode 格式处理⽂本字符,因此,字符本身是不会 有问题的。之所以出现乱码,原因在于 Qt 不知道将 Unicode 字符以何种⽅式显示 出来。⽂本⽂件含有简体中⽂,应指定为GBK。 按⾏读取如下:

#include<QTextCodec>

//指定为GBK
QTextCodec *codec = QTextCodec::codecForName("GBK");
	
//打开⽂件
QFile file("1.txt");

//如果打开⽂件失败,直接退出
if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
	return;

//当未到达⽂件结束位置
while(!file.atEnd())
{
    //读取⼀⾏⽂本数据
    QByteArray line = file.readLine();
    //将读取到的⾏数据转换为Unicode
    QString str = codec->toUnicode(line);
    //将得到的字符设置到编辑框中显示
    ui->edit->append(str);
}

3) 我们需要使⽤ QTextStream 类实现对纯⽂件⽂件的读写,QTextStream可以以 QFile、QTemporaryFile、QBuffer、QTcpSocket、QUdpSocket等IO设备类结 合使⽤。 QTextStream 和 QDataStream 的使⽤类似, 只不过它是操作纯⽂本⽂ 件的。

QTextStream 会⾃动将 Unicode 编码同操作系统的编码进⾏转换, 这⼀操作对 开发⼈员是透明的。 它也会将换⾏符进⾏转换, 同样不需要⾃⼰处理。 QTextStream 使⽤ 16 位的 QChar 作为基础的数据存储单位, 同样, 它也⽀持 C++QT 编程 实战应⽤151标准类型, 如 int 等。 实际上, 这是将这种标准类型与 字符串进⾏了相互转换。

使⽤ : <<QString //向QTextStream流中写⼊内容

使⽤QTextStream类写⽂件:

QFile data("file.txt");
if (data.open(QFile::WriteOnly | QIODevice::Truncate))
{
    QTextStream out(&data);
    out << "The answer is " << 42;
}

默认情况下, QTextStream 的编码格式是 Unicode, 如果我们需要使⽤另外的 编码, 可以使⽤:stream.setCodec(“UTF-8”);这样的函数进⾏设置或者将 QTextStream对象设定为是否⾃动识别Unicode编码(例如⽂本中有汉字时)。

void QTextStream::setAutoDetectUnicode(bool enabled)

//输⼊⽂件读取
QFile fileOpen("d://file.txt");
if(! fileOpen.open(QFile::ReadOnly | QIODevice::Text))
	qDebug() << fileOpen.errorString();
QTextStream in(&fileOpen); //创建输出流
while(!in.atEnd())
{
    QString oneLine = in.readLine(); //读取⼀⾏
    qDebug() << oneLine;
}

QFileInfo类提供了与系统⽆关⽂件的⽂件信息,包括⽂件的名称、⽂件系统中的 位置(路径)、⽂件的访问权限以及是否是⼀个⽬录或者符号链接等。QFileInfo 也可以获取⽂件的⼤⼩和最近⼀次修改⽂件的时间,还以获取Qt资源的相关信 息。

QFileInfo指向的⽂件可以在QFileInfo对象构建时设置,或者以后使⽤setFile()来 设置。也可以使⽤exists()函数来查看⽂件是否存在,只⽤size()获取⽂件的⼤ ⼩。

三、QFileInfo⽂件信息

QFileInfo类中常⽤的⽅法有:

QFileInfo类的构造函数:

构造⼀个空的QFileInfo对象,之后可以使⽤setFile()⽅法来指定与其关联的⽂件;

QFileInfo :: QFileInfo();

构造⼀个关联到⽂件file的QFileInfo对象,file参数指定⽂件名,可以是绝对路径,也可以是相对 路径;

QFileInfo :: QFileInfo(const QString &file);

使⽤⼀个QFile对象来构造QFileInfo对象;

QFileInfo :: QFileInfo(const QFile &file);

返回不保护路径及后缀的⽂件名,如myfile.tar.gz的baseName为myfile;

QString QFileInfo :: baseName() const;

返回包括⽂件名在内的⽂件的绝对路径;

QString QFileInfo :: absoluteFilePath() const;

返回不包括⽂件名在内的⽂件的绝对路径

QString QFileInfo :: absolutePath() const;

返回⽂件名,不包含⽂件路径,如果返回⽂件名为乱码,说明⽂档编码格式不正 确,QT读取格式为UTF-8,使⽤info.fileName().toUtf8().data()后即可

QFileInfo::fileName()

返回⽂件基名:completeBaseName()

QFileInfo fi("/tmp/archive.tar.gz");
QString base = fi.completeBaseName(); // base = "archive.tar"
注意:当⽂件后缀⼤于2个时,只获取第⼀个后缀,若少于两个则不获取后缀

返回⽂件后缀

QString QFileInfo::suffix() const

返回⽂件⼤⼩:size()

qint64 QFileInfo::size() const

⽂件相关的判断函数:

判断⽂件存不存在

bool QFileInfo::exists() const

判断是否是⽂件:isFile()

bool QFileInfo::isFile() const

.如果该对象指向⽂件或指向指向⽂件的符号链接,则返回true。如果对象指向的不是⽂件,例如 ⽬录,则返回false

判断是否是⽂件夹:isDir()

bool QFileInfo::isDir() const

判断⽂件是否可执⾏:isExecutable()

bool QFileInfo::isExecutable() const

判断⽤户是否可以读数据:isReadable()

bool QFileInfo::isReadable() const //如果⽤户可以读取⽂件,则返回true;否则返 回false

判断⽤户是否可写:isWritable()

bool QFileInfo::isWritable() const

判断对象是否指向⼀个根⽬录:isRoot()

bool QFileInfo::isRoot() const

QFile file("in.txt");
QFileInfo info(file);
qDebug() << info.isDir();
qDebug() << info.isExecutable();
qDebug() << info.baseName();
qDebug() << info.completeBaseName();
qDebug() << info.suffix();
qDebug() << info.completeSuffix();

其他:

  • 返回⽂件创建时间和⽇期:created()
  • 返回⽂件最后⼀次修改的⽇期和时间:lastModified()
  • 返回最后⼀次访问⽂件的⽇期和时间:lastRead()
  • 返回⽂件组:group()
  • 返回⽂件组ID:groupId()
  • 返回⽂件的所有者:owner()
  • 返回⽂件的所有者ID:ownerId()
  • .设置⽂件路径:setFile()

​ setFile(const QString & file)

​ setFile(const QFile & file)

​ setFile(const QDir & dir, const QString & file)

四 、⽬录操作QDir

QDir类提供了访问系统⽬录结构及其内容的与平台⽆关的⽅式。QT使⽤“/”作为 通⽤的⽬录分隔符,使⽤时需要包含头⽂件#include 。

QDir类对象所关联的⽬录路径可以使⽤path()函数获得,

可以使⽤setPath()⽅法来设置新的路径;

可以使⽤⽅法absolutePath()来获得⽬录的绝对路径。

⽬录名可以使⽤dirName()⽅法来获得,该⽅法返回绝对路径中的最后⼀个项⽬,

即⽬录名,但如果QDir关联的是当前⼯作⽬录,则返回"."。

可以使⽤mkdir()⽅法来创建⼀个⽬录;

使⽤rename()⽅法来对关联⽬录进⾏重命名;

使⽤rmdir()⽅法来移除⼀个⽬录;

使⽤exists()⽅法检测⽬录是否存在;

使⽤refresh()⽅法来刷新⽬录内容。

可以使⽤count()⽅法来获得QDir类对象关联的⽬录中的条⽬数⽬;

可以使⽤entryList()获取所有条⽬的名称;

可以使⽤entryInfoList()来获取条⽬的QFileInfo内容。

可以使⽤filePath()及absoluteFilePath()来获得QDir中指定⽂件的路径名,但这两 个函数均不检查指定的⽂件是否存在;

可以使⽤remove()⽅法来删除指定⽂件;

可以使⽤过滤器来获取指定类型的⽂件,当⽂件符合过滤器指定条件时被保留;

过滤器中的内容实际上是⼀个stringList。

#include<QDir>
QDir* dir=new QDir("D://ppp"); //创建⽬录对象
QStringList mydir=dir->entryList(QDir::Files,QDir::Name); //具体参数⻅下表
	qDebug()<<mydir<<endl;
//剥离掉路径,只返回⽬录的名字
QString str=dir->dirName();
	qDebug()<<str<<endl;
	//返回⽬录的数量
	qDebug()<<dir->count();
QString str1=dir->currentPath(); //返回应⽤程序当前⽬录的绝对路径
	qDebug()<<str1;
dir->cd("d:/1111"); //改变dir的⽬录
qDebug()<<dir->current()<<endl; //返回应⽤程序当前⽬录
qDebug()<<dir->dirName()<<endl; //返回⽬录的名称

参数1–Filter枚举变量:可选

QDir::NoFilter 默认 返回⽬录下的所有⽬录和⽂件

(" . " , " … " , “a.jpg” , “b.jpg” , “c.jpg” , “d.jpg” , “dongwu” , “linsi.txt” , “ziwu”)

QDir::Files 返回所有⽂件的⽂件名,不包括⽂件夹

(“a.jpg” , “b.jpg” , “c.jpg” , “d.jpg” , “linsi.txt”) QDir::Dirs 只返回⼀层⽬录 (" . " , " … " , “dongwu” , “ziwu”)

QDir::AllDirs 列出所有⼀层⽬录,不对⽬录名进⾏过滤

(" . " , " … " , “dongwu” , “ziwu”)

QDir::Drives 列出逻辑驱动器名称,该枚举变量在Linux/Unix中将被忽略

() 返回是空 不知为何 知道的请告诉我???

QDir::AllEntries 其值为Dirs | Files | Drives,列出⽬录、⽂件、驱动器及软链接等所有⽂件

(" . " , " … " , “a.jpg” , “b.jpg” , “c.jpg” , “d.jpg” , “dongwu” , “linsi.txt” , “ziwu”)

QDir::NoSymLinks 不列出符号链接;

QDir::NoDotAndDotDot 不列出⽂件系统中的特殊⽂件.及…;

QDir::NoDot 0x2000 不列出.⽂件,即指向当前⽬录的软链接

QDir::NoDotDot0x4000 不列出…⽂件;

QDir::Readable 列出当前应⽤有读权限的⽂件或⽬录;

QDir::Writable 列出当前应⽤有写权限的⽂件或⽬录

QDir::Executable 列出当前应⽤有执⾏权限的⽂件或⽬录

以上的Readable、Writable及Executable均需要和Dirs或Files枚举值联合使⽤;

QDir::Modified 列出已被修改的⽂件,该值在Linux/Unix系统中将被忽略;

QDir::Hidden 列出隐藏⽂件;

QDir::System 列出系统⽂件;

QDir::CaseSensitive 设定过滤器为⼤⼩写敏感

参数2–SortFlag枚举变量 可选

这个枚举变量描述的是QDir如何排列由 entryList() 或 entryInfoList() 返回的条⽬

QDir::Name - 按名称排序。

QDir::Time - 按时间排序(修改时间)。

QDir::Size - 按⽂件⼤⼩排序。

QDir::Unsorted - 不排序。

QDir::SortByMask - Name、Time和Size的掩码。

QDir::DirsFirst - ⾸先是⽬录,然后是⽂件。

QDir::Reversed - 相反的排序顺序。

QDir::IgnoreCase - 不区分⼤⼩写进⾏排序。

QDir::DefaultSort - 内部标记。

前四种中你只能指定⼀个。

五、⼆进制⽂件读写

QDataStream 提供了基于 QIODevice 的⼆进制数据的序列化。 数据流是⼀种⼆ 进制流, 这种流完全不依赖于底层操作系统、 CPU 或者字节顺序(⼤端或⼩端)。

QDataStream 既能够存取 C++ 基本类型, 如 int、 char、 short 等, 也可以存 取复杂的数据类型, 例如⾃定义的类。 实际上, QDataStream 对于类的存储, 是将复杂的类分割为很多基本单元实现的。

QFile file("file.dat");
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
out << QString("the answer is");
out << (qint32)42;
file.close(); // 如果不想关闭⽂件, 可以使⽤ file.flush()将数据从缓存写⼊到⽂件

我们将刚刚创建的 file 对象的指针传递给⼀个 QDataStream 实例 out。 类似于 std::cout 标准输出流, QDataStream 也重载了输出重定向<<运算符。 后⾯的代 码就很简单了: 将“the answer is” 和数字 42 输出到数据流。 由于我们的 out对 象建⽴在 file 之上, 因此相当于将问题和答案写⼊ file。

需要指出⼀点: 最好使⽤ Qt 整型来进⾏读写, ⽐如程序中的 qint32。 这保证了 在任意平台和任意编译器都能够有相同的⾏为。

//接下来我们将存储到⽂件中的答案取出来
QFile file("file.dat");
file.open(QIODevice::ReadOnly);
QDataStream in(&file);
QString str;
qint32 a;
in >> str >> a;

需要注意的是, 你必须按照写⼊的顺序, 将数据读取出来。 顺序颠倒的话,程序 ⾏为是不确定的, 严重时会直接造成程序崩溃。

其他---------------------------------------------------------------------- -------

⾸先记录⼀下QString,QByteArray,char * 之间的转换

(1) QString -> QByteArray

QString buf = “123”;

QByteArray a = buf.toUtf8(); //中⽂

a = buf.toLocal8Bit(); //本地编码

123

(2) QByteArray -> char *

char *b = a.data();

1

(3) char * -> QString[⽹络编程常常涉及到]

char *p = “abc”;

QString c = QString§;

08线程的基本使用

一、QT线程与进程使⽤

多线程对于需要处理耗时任务的应⽤很有⽤,可以⼀⽅⾯响应⽤户的界⾯操作, 另⼀⽅⾯在“后台”进⾏耗时操作,⽐如⼤量运算、复制⼤⽂件、⽹络传输等。

QT通过三种形式提供了对线程的⽀持,分别是平台⽆关的线程类、线程安全的事 件投递、跨线程的信号-槽连接。

QThread是⼀个跨平台的多线程解决⽅案,使⽤QThread类可以⽅便快捷地创建 管理多线程。⽽多线程之间的通信也可使⽤Qt特有的“信号-槽”机制实现。

QMutex 提供相互排斥的锁,或互斥量,QMutexLocker 是⼀个辅助类,⾃动对 QMutex 加锁与解锁,给QMutexLocker传递⼀个qmutex对象来上锁和解锁

要设置线程的名称,可以在启动线程之前调⽤setObjectName()。如果不调⽤ setObjectName(),线程的名称将是线程对象的运⾏时类型(QThread⼦类的类名)。

二、QThread中的关键成员函数介绍

void run() :线程体函数,⽤于定义线程功能(执⾏流)

void start() :启动函数,将线程⼊⼝地址设置为run函数

void stop():停⽌线程

void terminate() :强制结束线程(不推荐), 所有线程都结束后,进程才结束

QThread::currentThreadId():返回当前线程的id

QThread::sleep(unsignedlongsecs):让当前的线程休眠指定的秒数

void quit(); //通知线程事件循环退出,相当于调⽤了QThread::exit(0)

void setObjectName() //设置线程名称,在启动线程之前调⽤,线程的名称将是 线程对象的运⾏时类型(QThread⼦类的类名)

线程的状态查询:

bool isFinished () const 线程是否已经退出

bool isRunning () const 线程是否处于运⾏状态

相关信号:

当线程启动和结束时,QThread会发送信号started()和finished()

三、创建线程步骤

这是官⽅⼿介绍的⼀种常⽤的⽅法:

a. ⼦类化 QThread,创建对象,并调⽤start()函数

b. 重载 run 函数,run函数内有⼀个while或for的死循环(模拟耗时操作)

c. 设置⼀个标记为来控制死循环的退出。

例1:实现⼦线程与当前的主线程同时⼯作

#include<QThread>
#⽂件声明⼀个类
class mythread:public QThread
{
private:
	void run();
};

//ccp⽂件多线程执⾏的内容将通过重写该虚函数实现
void mythread:: run()
{
    qDebug()<<"开始采摘苹果"<<QThread::currentThreadId()<<endl;
    for(int i=0; i<5;i++)
    {
        qDebug()<<"####开始采第"<<i+1<<"个苹果"<<endl;
        QThread::sleep(1);
	}
	qDebug()<<"####采摘完成"<<endl;
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    mythread tt; //创建⼀个进程对象
    tt.start();
    // while(1){ //检测⼦线程完成在执⾏第⼆个任务
    // if(tt.isFinished()==true) break;
    // }
    qDebug()<<QThread::currentThreadId()<<endl;
    for(int i=0; i<5;i++)
    {
        qDebug()<<"$$$$$$开始采摘第"<<i+1<<"苹果"<<endl;
        QThread::sleep(1);
	}
    qDebug()<<"$$$$$$采摘完成"<<endl;
    tt.wait();
    qDebug()<<"end"<<endl;
    return a.exec();
}

例2:利⽤信号与槽机制实现两个线程之间的通信实例

//头⽂件-------------------
#include<QThread>
//继承线程类,定义⼀个信号⽤来关联⼀个槽函数
class mythread : public QThread
{
	Q_OBJECT
private:
	void run();
    
signals: //声明⼀个信号
	void over();
};

class MainWindow : public QMainWindow
{
	Q_OBJECT
        
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    
    mythread *thread; //定义⼀个线程对象
    
private slots:
	void start_two_tree(); //
    
private:
	Ui::MainWindow *ui;
};

//-------------------cpp⽂件----------------------------
MainWindow::MainWindow(QWidget *parent)
	: QMainWindow(parent)
	, ui(new Ui::MainWindow)
{
	ui->setupUi(this);
        
	thread=new mythread; //定义⼀个线程对象
	thread->setObjectName(QString("okk"));//设置线程对象的名字,注意在启动前设置
	connect(thread,&mythread::over,this,&MainWindow::start_two_tree);//连接槽函数
}

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

//主线程要调⽤的任务函数
void MainWindow:: start_two_tree()
{
    qDebug()<<QThread::currentThreadId()<<endl;
    for(int i=0; i<5;i++)
    {
        qDebug()<<"$$$$$$开始采摘第"<<i+1<<"苹果"<<endl;
        QThread::sleep(1);
    }
    qDebug()<<"$$$$$$采摘完成"<<endl;
    qDebug()<<thread->objectName()<<endl; //获取线程对象的名字
}

//⼦线程的任务函数 通过重新run虚函数实现
void mythread:: run()
{
    qDebug()<<"开始采摘苹果"<<QThread::currentThreadId()<<endl;
    for(int i=0; i<5;i++)
    {
        qDebug()<<"####开始采第"<<i+1<<"个苹果"<<endl;
        QThread::sleep(1);
    }
    qDebug()<<"####采摘完成"<<endl;
    emit over(); //⼦线程向主线程发送⼀个信号
}

//主函数
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.thread->start();
    
    return a.exec();
}

09网络编程

一、QT之网络编程

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

二、实例


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

10QT操作数据库

⼀、QT sql模块简介

qt中的QT sql模块提供了对数据库的⽀持,⽀持常⽤的有:MySQL、Oracle、 MS SQL Server、SQlite等。

在使⽤数据库时,需要查看安装的QT中⽀持的驱动列表。⼀般可以在QT安装⽬录 中的plugins/sqldrivers⽂件夹中查看所有的驱动插件⽂件。

qtsql模块使⽤数据库驱动插件来和不同的数据库接⼝进⾏通信,由于sql接⼝的模 块是独⽴于数据库的,因此这些代码都包含在驱动中,我们在使⽤时,需要在 xxx.pro⼯程⽂件中需要添加如下:QT += sql,在使⽤的源码⽂件中添加头⽂件 #include

可以通过代码查看有哪些开源版本:

#include

qDebug() << QSqlDatabase::drivers();

(“QSQLITE”, “QMYSQL”, “QMYSQL3”, “QODBC”, “QODBC3”, “QPSQL”, “QPSQL7”)

默认并不⽀持QMYSQL,驱动库⽂件是已经⽣成好的,

编译mysql动态库参考⽹站:

https://www.cnblogs.com/lbx-cnblogs/p/13521678.html

https://blog.csdn.net/qq_21291397/article/details/107655591

QT SQL 模块的主要类:

QSqlDatabase ⽤于建⽴与数据库的连接。

QSqlDriver ⽤于访问具体的SQL数据库的底层抽象类。

QSqlDriverCreator 为某个具体的数据库驱动提供SQL驱动的模板类。

QSqlDriverCreatorBase 所有SQL驱动器的基类。

QSqlDriverPlugin ⽤于定制QSqlDriver插件的抽线基类。

QSqlError SQL数据库错误信息,⽤于访问上⼀次出错的信息。

QSqlField 操作数据表或视图(View)字段的类。

QSqlIndex 操作数据库索引的类。

QSqlQuery 执⾏各种SQL语句的类。

QSqlQueryModel SQL查询结果数据的只读模型(data model),⽤于SELECT查 询结果数据记录的只读显示。

QSqlRecord 数据记录操作的类。

QSqlRelation 存储SQL外键信息的类,⽤于QSqlRelationTableModel数据源 中设置代码字段与关联数据表的关系。

QSqlRelationalDelegate ⽤于QSqlRelationTableModel的⼀个代码字段的显示 和编辑代理组件,⼀般是⼀个QComboBox组件,下拉列表中⾃动填充代码表的代 码字段对应的实际内容。

QSqlRelationalTableModel ⽤于⼀个数据表的可编辑的数据模型,⽀持代码字 段外键。

QSqlResult 访问SQL数据库的抽象接⼝。

QSqlTableModel 编辑⼀个单⼀数据表的数据模型类。

QDataWidgetMapper ⽤于界⾯组件与字段之间实现映射,实现字段内容⾃动 显示的类。

⼆、QT中对mysql的基本操作

1)创建数据库链接

加载数据库驱动,获取连接对象;

使⽤QSqlDatabase的静态⽅法,返回连接对象:

QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName = QLatin1String(defaultConnection))

其中:

type:数据库驱动类型,可通过 QSqlDatabase::drivers()静态函数获取

​ “QSQLITE”

​ “QMYSQL”

​ “QMYSQL3”

​ “QPSQL”

​ “QPSQL7”

connectionName:连接对象名称,若缺省,获取⼀个⽆名连接对象。

例⼦: QSqlDatabase db = QSqlDatabase::addDatabase(“QSQLITE”);

2)数据库的链接参数说明

设置数据库连接的参数:

db.setHostName(); //⽤于远程数据库

db.setDatabaseName(); //指定数据库名称

db.setUserName(); //指定连接数据库的⽤户名

db.setPassword(); //指定连接数据库的⽤户名对应密码

3)打开数据库

db.open() ; //返回true则连接成功,否则连接失败

4)关闭数据库

db.close();

#注意:需要在.pro⽂件中添加⼀⾏引⼊QT += sql
#include<QtSql>

QSqlDatabase database;
database=QSqlDatabase::addDatabase("QMYSQL");//创建数据库连接,并为其命名testConnect
连接数据库主机名,这⾥需要注意(若填的为”127.0.0.1“,出现不能连接,则改为localhost)
database.setHostName("127.0.0.1"); //连接数据库主机名,这⾥需要注意(若填的为”127.0.0.1“,出现不能连接,则改为localhost)
database.setDatabaseName("xxx");
database.setPort(3306); //连接数据库端⼝号,与设置⼀致
database.setUserName("root"); //数据库⽤户名,与设置⼀致
database.setPassword("123456"); //数据库密码,与设置⼀致
if (!database.open()) {
	qDebug()<<"连接数据库失败"<<endl;}
else
	qDebug()<<"连接数据库成功"<<endl;

5)数据库的增删改插

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

例1:遍历表中的所有列字段

QSqlQuery query( db);
query.exec("select * from student");
QSqlRecord rec;
while(query.next())
{
    rec = query.record();
    //QVariant转其他类型
    int value1 = query.value(0).toInt();// //获取id属性的值,并转换为int型
    QString value2 = query.value(1).toString();
    QString value3 = query.value(2).toString();
    QString value4 = query.value(3).toString();
    qDebug()<<value1<<value2<<value3<<value4<<endl;
}

>>>:
1 "赵雷" "1990-01-01" "男"
2 "钱电" "1990-12-21" "男"

例2:遍历表中指定字段值

根据字段名称,获得字段的位置:int QSqlRecord::indexOf(constQString &name) const

while(query.next())
{
    rec = query.record();
    int s_namecol = rec.indexOf("s_name");//根据字段名去获取字段的位置
    //QVariant转其他类型
    QString value1 = query.value(s_namecol).toString();
    qDebug()<<value1<<endl;
}

例3:查询记录数,字段数量和记录跳转

QSqlQuery query( db);
query.exec("select * from student");
qDebug()<<query.size()<<endl;//记录数⽬
query.seek(2);//
QSqlRecord rec= query.record();
qDebug()<<rec.value(1)<<endl;//QVariant(QString, "孙⻛")
qDebug()<<rec.count()<<endl; //字段的数量可以通过count()获取

例4:在sql语句中使⽤变量

QSqlQuery query( database);
int id=3;
query.exec(QString("select * from student where s_id=%1").arg(id));
qDebug()<<query.at()<<endl;//显示-1
query.next();//默认返回的结果集执⾏⼀次next函数才指向第⼀条记录。
QSqlRecord rec= query.record();
qDebug()<<rec.value(1)<<endl;//QVariant(QString, "孙⻛")

例5:插⼊,修改与删除数据

QSqlQuery query(database);// 定义⼀个查询对象
query.exec("insert into student VALUES ('13','ww','1991-2-3','男')");
//⼀次插⼊两条记录
query.exec("insert into student VALUES ('14','ww1','1991-2-3','男'),
('15','ww2','1991-2-3','男')");
//将id等于15的⼈名修改为⽼杜
query.exec("update student set s_name='laodu' where s_id='15'");
三、模型视图

在这里插入图片描述


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

11界面美化

⼀、样式表简介

⼀个完善的应⽤程序不仅应该有实⽤的功能,还要有⼀个漂亮的外观,这样才能使应⽤程序更加友好,更加吸引⽤户。作为⼀个跨平台的UI开发框架,Qt提供了强⼤⽽灵活的界⾯外观设计机制。

Qt样式表是⼀个可以⾃定义部件外观的⼗分强⼤的机制。Qt样式表的概念、术语和语法都受到了HTML的层叠样式表(Cascading StyleSheets,CSS)的启发,不过与CSS不同的是,Qt样式表应⽤于部件的世界。

Qt中的各种⻛格是⼀组继承⾃QStyle的类,QStyle类是⼀个抽象基类,封装了⼀个GUI的外观,Qt的内建(built-in)部件使⽤它来执⾏⼏乎所有的绘制⼯作,以确保它们看起来可以像各个平台上的本地部件⼀样。

例如:对⼀个窗体定义样式表如下:

Qwidget { 
    background-color: rgb (255,255,0) ; 
    color: rgb (255,0,0 ) ; 
    font: 12pt"宋体"; 
}

1)样式表语法

QSS包含了⼀个样式规则序列,⼀个样式规则由⼀个选择器和声明组成,选择器指定哪些部件由规则影响,声明指定哪些属性应该在部件上进⾏设置。

例如:

QPushButton { color: red }

1.样式表 StyleSheet 
    基本语法规则: 
    1. 选择器(selector) 
    2. 声明 
    例⼦: 
    QPushButton{color: rgb(255, 0, 0);} 

	选择器:QPushButton 
    声明: {color: rgb(255, 0, 0);} 

	选择器可⽀持多个,如果有多个逗号隔开 
    QPushButton,QLabel{color: rgb(255, 0, 0);} 

    属性: color; 
    属性值:rgb(255, 0, 0) 
    
    属性可⽀持多个,如果有多个分号隔开 
    QPushButton,QLabel{color: rgb(255, 0, 0); background-color: rgb(85, 0, 255);} 

2.选择器: 
    1.全局选择器: * ; 匹配所有控件 
    2.类型选择器 QLabel ; 匹配QLabel及其⼦类的⼀个实例 
    3.ID选择器 QLabel#label_2 ; 匹配对象名为 label_2 的实例窗⼝ 
    4.后代选择器 QWidget QLabel ; 匹配QWidget类的⼦类中所有QLabel类型实例 
    5.⼦选择器:QDialog > QPushButton 匹配属于QDialog直接⼦类的QPushButton所 有实例。
    6.⼦控件: QSlider::handle ; 匹配滑动条的 滑块; QComboBox::down-arrow ; 匹配组合框的下拉箭头; 
    7.伪状态 QPushButton : hover: ⿏标悬停在按钮上; : pressed : checked
        
    特殊说明: 
    1、例如对于样式复杂的部件,需要访问⼦控件,例如:QComboBox的下拉按钮或QSpinBox的上下 箭头。
        选择器可能包含⼦控件,使得可以限制特有部件⼦控件的应⽤规则。 
        例如: QComboBox::drop-down { image: url(dropdown.png) } 
        指定了QComboBoxe下拉按钮样式 
    2、选择器可以包含伪状态,意味着限制基于部件状态的应⽤程序规则。 
       伪状态出现在选择器后⾯,⽤冒号(:)关联。例如,⿏标划过按钮: 
       QPushButton:hover { color: white } 
       伪状态可以⽤感叹号(!)运算符表示否定: QRadioButton:!hover { color: red } 
    3. 常⽤属性: 
        1.background-color 背景⾊
        2.background-image 背景图 
        3.border: 外边框 
        4.border-radius: 圆⻆半径 
        5.border-style: 边框⻛格: 实线 虚线 点划线; 
            
        font-size:15px;

**2)级联效应 **

QSS可以在QApplication、⽗部件、⼦部件中设置。

可以使⽤QApplication::setStyleSheet()函数设置到整个应⽤程序上,也可以使⽤

QWidget::setStyleSheet()设置到某⼀个部件以及⼦部件上。如果在不同的级别都

设置了样式表,QT会使⽤所有有效的样式表,称为样式表的层叠。

3)样式设置

设置样式的常⻅做法:

\1. 在ui设计⻚⾯,找到控件的styleSheet的属性,打开输⼊框,输⼊固定格式的指令设置:

\2. 使⽤API接⼝设置,setStyleSheet接⼝。

在设计模式使⽤Qt样式表

1.新建Qt Gui应⽤,项⽬名称为myStyle,其他保持默认即可。完成后打开

mainwindow.ui进⼊设计模式,然后拖⼊⼀个Push Button按钮。

2.在按钮部件上右击,选择“改变样式表”菜单项,在弹出的编辑样式表对话框中点击“添加颜⾊”下拉框,然后选择background-color,我们为其添加背景颜⾊。

这时会弹出选择颜⾊按钮,⼤家可以随便选择⼀个颜⾊,这⾥选择了红⾊,然后点击确定按钮关闭对话框。添加好的代码如下图所示。这种⽅法可以快速设置样式表,当然我们也可以⾃⼰⼿动来添加代码。

3.完成后⼤家可能发现按钮的颜⾊并没有改变,不要着急,这时运⾏程序,发现已经有效果了。

4.其实在设计模式还可以很容易地使⽤背景图⽚,这个需要使⽤Qt资源,⼤家可以试试,这⾥就不再介绍。

在代码中设置Qt样式表:

既然在设计器中可以使⽤样式表,那么使⽤代码就⼀定可以实现。在代码中可以使⽤setStyleSheet()函数来设置样式表,不过⽤两种设置⽅法。

1.设置所有的相同部件都使⽤相同的样式。我们在mainwindow.cpp的构造函数中添加如下代码:

setStyleSheet(“QPushButton { color: white }”);

2.那么怎样才能只给特定的⼀个按钮设置样式表呢,这就需要使⽤第⼆种⽅式 了。我们接着在mainwindow.cpp构造函数中添加代码:

ui->pushButton->setStyleSheet(“color: blue”);

ui->pushButton->setStyleSheet(“background-color:red; color: blue”);

3.在Qt Style Sheets Reference关键字对应的帮助⽂档的List of Pseudo-States⼀项中列出了Qt⽀持的所有的伪状态。

正常状态下:⿊底(背景⾊),⽩字(前景⾊),圆⻆,向外凸起;

⿏标停留:背景和前景都反⾊;

⿏标按下:背景⾊变为淡蓝⾊,向内凹陷。

代码:

ui->pushButton_GoToProcess->setStyleSheet("QPushButton{background- color:black;\ 
color: white; border-radius: 10px; border: 2px groove gray;\ 
border-style: outset;}"按键本⾊ 
"QPushButton:hover{background-color:white; color: black;}" ⿏标停放时的⾊彩 "QPushButton:pressed{background-color:rgb(85, 170, 255);\ border-style: inset; }"⿏标按下的⾊彩 
);

4.⼤家可以在Qt Style Sheets Examples⻚⾯找到很多相关的例⼦来学习,例如,下⾯是

QSpinBox部件的⼀段样式表:

/****************按钮部件*******************/ 
QPushButton{ 
    background-color: rgba(100, 225, 100, 30);/*背景⾊*/ 
    border-style: outset; /*边框样式*/ 
    border-width: 4px; /*边框宽度为4像素*/ 
    border-radius: 10px; /*边框圆⻆半径*/ 
    border-color: rgba(255, 225, 255, 30);/*边框颜⾊*/ 
    font: bold 14px;/*字体*/ 
    color:rgba(0, 0, 0, 100);/*字体颜⾊*/ 
    padding: 6px; /*填衬*/ 
}

QPushButton:hover{ /*⿏标悬停在按钮上时*/ 
    background-color:rgba(100,255,100, 100); 
    border-color: rgba(255, 225, 255, 200); 
    color:rgba(0, 0, 0, 200); 
}

QPushButton:pressed { /*按钮被按下时*/ 
    background-color:rgba(100,255,100, 200); 
    border-color: rgba(255, 225, 255, 30); 
    border-style: inset; color:rgba(0, 0, 0, 100); }

/****************滑块部件*******************/ 
QSlider::handle:horizontal { /*⽔平滑块的⼿柄*/ 
    image: url(:/image/sliderHandle.png); 
}

QSlider::sub-page:horizontal { /*⽔平滑块⼿柄以前的部分*/ 
    border-image: url(:/image/slider.png);/*边框图⽚*/ 
}

Qt样式表可以存放在⼀个以.qss为后缀的⽂件中,可以在程序中调⽤不同的.qss⽂件实现换⽪肤功能。在代码⾥我们可以通过setstylesheet函数来设置widget的样式表。

setStyleSheet("QPushButton { color: white }"); 
QFile file(":/new/prefix1/mystyle.qss"); 
	if(file.open(QIODevice::ReadOnly)) 
	{a.setStyleSheet(file.readAll()); 
	 	file.close(); 
	} 

//Qt 资源系统⽀持搜索路径列表。如果你⽤ ":" 代替 ":/" 作为前缀, 则会使⽤搜索路径列表来搜索资源。程序启动时搜索路径列表为空,可以⽤ QDir::addSearchPath() 在其中增加路径。
二、调⾊板介绍

调⾊板QPalette类包含了部件各种状态的颜⾊组。⼀个调⾊板包含3种状态:激活(Active)、失效(Disabled)和⾮激活(Inactive)。Qt中的所有部件都包含⼀个调⾊板,并且使⽤各⾃的调⾊板来绘制它们⾃身,这样可以使⽤户界⾯更容易配置,也更容易保持⼀致。调⾊板中的颜⾊组包括:

  • 激活颜⾊组QPalette::Active,⽤于获得键盘焦点的窗⼝;
  • ⾮激活颜⾊组QPalette::Inactive,⽤于其他的窗⼝;
  • 失效颜⾊组QPalette::Disabled,⽤于由于⼀些原因⽽不可⽤的部件(不是窗⼝)。

要改变⼀个应⽤程序的调⾊板,可以先使⽤QAppliCation::palette()函数来获取其调⾊板,然后对其进⾏更改,最后再使⽤QApplication::SetPalette()函数来使⽤该调⾊板。

更改了应⽤程序的调⾊板,会影响到该程序的所有窗⼝部件。如果要改变⼀个部件的调⾊板,可以调⽤该部件的palette()和setPalette()函数,这样只会影响该部件及其⼦部件。

//获取 pushButton 的调⾊板 
QPalette palette1 = ui->pushButton->palette(); 
//设置按钮⽂本颜⾊为红⾊ 
palette1.setColor(QPalette::ButtonText,Qt::red); 
//设置按钮背景⾊为绿⾊ 
palette1.setColor(QPalette::Button,Qt::green); 
//pushButton 使⽤修改后的调⾊板 
ui->pushButton->setPalette(palette1); 
//设置 lineEdit 不可⽤ 
ui->lineEdit->setDisabled(true); 
QPalette palette2 = ui->lineEdit->palette(); 
//设置⾏编辑器不可⽤时的背景颜⾊为蓝⾊ 
palette2.setColor(QPalette::Disabled,QPalette::Base,Qt::blue); ui->lineEdit->setPalette(palette2);

设置调⾊板颜⾊时可以使⽤setColor()函数,这个函数需要指定颜⾊⻆⾊(Color Role)。在QPalette中,颜⾊⻆⾊⽤来指定该颜⾊所起的作⽤,例如是背景颜⾊或者是⽂本颜⾊等,主要的颜⾊⻆⾊如下表所列。

常量描述
QPalette::Window⼀个⼀般的背景颜⾊
QPalette::WindowText⼀个⼀般的前景颜⾊
QPalette::Base主要作为输⼈部件(如QLineEdit)的背贵⾊,也可⽤作QComboBox的下拉列表的背景⾊
QPalette::AlternateBase在交种⾏颜⾊的视图中作为交替背景⾊
QPalette::ToolTipBase作为QToolTip和QWhatsThis的背景⾊
QPalette::ToolTipText作为QToolTip和QWhatsThis的前景⾊
QPalette::Text和Base—起使⽤,作为前景⾊
QPalette::Button按钮部件背景⾊
QPalette::ButtonText按钮部件前景⾊

//设置背景

this->setAutoFillBackground(true); 
//设置背景图标,但是不能让背景图⽚⾃适应 
QPalette pt;//=this->palette(); 
QPixmap img(":/new/prefix1/myimg.png"); 
pt.setBrush(QPalette::Window,QBrush(img)); 
this->setPalette(pt); 

//缩放填充 
QSize picSize(1000,800);//设置图⽚的缩放尺⼨ 
QPalette pt; 
QPixmap img(":/new/prefix1/myimg.png"); 
QPixmap img1=img.scaled(picSize,Qt::KeepAspectRatio); 
pt.setBrush(QPalette::Window,QBrush(img1)); this->setPalette(pt);

//调整为⾃适应⼤⼩

//设置背景图标,但是不能让背景图⽚⾃适应 
QPalette pt;//=this->palette(); 
QImage img(":/new/prefix1/myimg.png"); 
QImage myimg=img.scaled(this->width(),this->height()); //设置⽐例 
pt.setBrush(QPalette::Window,QBrush(myimg)); //设置画笔 
this->setPalette(pt);

QImage主要在I/O和直接的像素级访问和操作上做了优化设计。如果要对图像进⾏像素级别的修改,就要⽤QImge,否则已被的图像加载,翻转,缩放等操作,就⽤QPixmap

12打包发布程序

设置应用程序图标

1.准备一个.ico格式图片。添加在项目中;

2.在工程配置文件.pro中添加一行内容:RC_ICONS = 图片名称

打包发布:

1.选择Release版本发布生成工程文件

2.在Release中找到应用程序,复制在空文件夹下,如:D:\test

3.cmd中打开Qt 5.14.2(MinGW 7.3.0 32-bit) //对应自己的编译器版本

4.输入cd D:\test

5.输入windeployqt.exe xxx.exe //xxx.exe对应本次的应用程序

(可选)制作安装包

innosetup-6.0.2操作流程:

https://zhuanlan.zhihu.com/p/142751241
  • 5
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Three笔记

有用的话赏点吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值