Qt复习

Qt review

Posted by XDong on December 13, 2020

1. 简单解释Qt以及优点 、Qt增加特性。

Qt是Trolltech(奇趣)公司的一个产品,是多平台的C++图形用户界面应用程序框架

Qt是一个跨平台应用程序和UI开发框架,可以理解为开发包或者库文件。 优良的跨平台特性( Windows 、Android 、IOS、Linux ),一次编写,处处编译:write once, compile anywhere。根据不同平台的本地观感生成相应的本地应用。

面向对象、丰富的API、信号与槽的消息机制、编程语言:C++ 以及java、支持2D/3D 图形渲染、支持OpenGL 、XML 支持国际化,多语言的支持、强大的工具,提高了开发的效率和质量帮助文档assistant,之后遵循LGPL协议,个人应用完全免费。

2. QtGUI应用程序的main()程序结构,QApplicate的作用?Qt项目组成?

  1. int main(int argc, char *argv[])
  2. QApplication类对象,用于管理应用程序的资源。
  3. Qt项目组成

项目组成

1. 菜单栏(Menu Bar)

有8个菜单选项,包含了常用的功能菜单:文件菜单、编辑菜单、构建菜单、调试菜单、analyze分析菜单、工具菜单、帮助菜单。工具菜单提供了快速定位菜单、版本控制工具菜单和外部工具菜单等。里面的选项菜单中包含了Qt Creator各个方面的设置选项:环境设置、文本编辑器设置、帮助设置、构建和运行设置、调试器设置和版本控制设置等。

2. 模式选择器(Mode Selector)

包含欢迎、编辑、设计、调试、项目和帮助6个模式,各个模式完成不同的功能,也可以使用快捷键来更换模式,它们对应的快捷键依次是Ctrl + 数字1~6。

3. 构建套件选择器(Kit Selector )

  • 包含了目标选择器(Targetselector)、运行按钮(Run)、调试按钮(Debug)和构建按钮(Building)4个图标。
  • 目标选择器用来选择要构建哪个项目,使用哪个Qt库,这对于多个Qt库的项目很有用。还可以选择编译项目的debug版本或是release版本。
  • 运行按钮可以实现项目的构建和运行;
  • 调试按钮可以进入调试模式,开始调试程序;
  • 构建按钮完成项目的构建。

4. 定位器(Locator)

  • 在QtCreator中可以使用定位器来快速定位项目、文件、类、方法、帮助文档以及文件系统。
  • 可以使用过滤器来更加准确地定位要查找的结果。
  • 可以在“工具→选项”菜单项中设置定位器的相关选项。

5. 输出窗格(Output panes)

这里包含了问题、搜索结果、应用程序输出、编译输出、Debugger Console、概要信息、版本控制7个选项,它们分别对应一个输出窗口,相应的快捷键依次是Alt + 数字1~7。

  • 问题窗口显示程序编译时的错误和警告信息;
  • 搜索结果窗口显示执行了搜索操作后的结果信息;
  • 应用程序输出窗口显示在应用程序运行过程中输出的所有信息;
  • 编译输出窗口显示程序编译过程输出的相关信息;
  • 版本控制窗口显示版本控制的相关输出信息。

3. 利用QtCreator创建项目时,提供的3个基类分别是什么,关系是怎样的?

  • QMainWindow:带有菜单栏和工具栏的主窗口类;
  • QDialog:是重要的信息显示和获取输入数据的用户界面对象,是各种对话框的基类;
  • QWidget: QWidget类是所有用户界面对象的基类,被称为基础窗口部件,继承自QObject类和QPaintDevice类。所有的窗口部件都继承自QWidget。
  • QObject类是所有支持Qt对象模型(Qt Object Model)的Qt对象的的基类;
  • QPaintDevice类是所有可以绘制的对象的基类。

4. 信号与槽机制作用,信号与槽关联函数connection()在那个类中定义,前4个参数的意义,两种关联(手动、自动)的区别。

1
Connect(sender,SIGNAL(signal),receiver,SLOT(slot));
  • Sender 发送信号的对象
  • SIGNAL(signal) 要发送的信号
  • Receiver 接受信号的对象
  • SLOT(slot) 要执行的槽函数

自动关联:

1
on_pushButton_clicked();

自动关联就是将关联函数整合到槽命名中。由字符“on”和发射信号的部件对象名,还有信号名组成。

自动关联更简便,用Qt设计器直接生成的槽就是使用自动关联。在编写程序时一般用手动关联。

5. 模态和非模态对话框(概念、创建、初始化、运行、取结果)。现实和隐藏使用的方法。(代码)

  • 模态对话框:就是在其没有被关闭之前,用户不能与同一个应用程序的其他窗口进行交互,直到该对话框关闭。这时往往是需要对话框的返回值进行下面的操作确认窗口。例如:选择“是”或“否”。
  • 非模态对话框:当被打开时,用户既可选择和该对话框进行交互,也可以选择同应用程序的其他窗口交互。弹出窗口之后,调用即刻返回,继续下面的操作。例如查找对话框。

代码:

1
2
3
4
5
6
7
8
9
10
11
    QDialog *dialog = new QDialog(this);
    dialog->setWindowTitle("Dialog");
//    非模态对话框
    dialog->show();

//    模态对话框
//    dialog->setModal(true);
//    dialog->show();

//    模态对话框
//    dialog->exec();

对话框模态:

  • 通过模态属性确定-setmodal(modal)
  • bool:默认非模态对话情况,对话框的该属性值是false;
  • true:设置成了模态对话框;

显示对话框方法:

  • exec():实现模态对话框;
  • show():可实现模态对话框,也可以实现非模态对话框;显示一个非模式对话框。控制权即刻返回给调用函数。弹出窗口是否模式对话框,取决于modal属性的值。
  • exec() 显示一个模式对话框,并且锁住程序直到用户关闭该对话框为止。函数返回一个DialogCode结果。enum DialogCode { Rejected, Accepted }

6. 标准对话框种类。

  • 颜色对话框(QColorDialog):提供了指定颜色的对话框窗口部件。在不同的系统平台下,颜色对话框的显示效果可能会有所不同,主要因系统主题风格而异,但是功能是相同的。
  • 文件对话框 (QFileDialog):提供了允许用户选择文件或者目录的对话框。
  • 字体对话框
  • 输入对话框
  • 消息对话框
  • 进度对话框
  • 错误信息对话框
  • 向导对话框

7. 布局管理器的任务,布局及相关的类(QHBoxLayout、QVBoxLayout、QGridLayout、QStackLayout)管理窗体上子窗口部件的布局方法,以及编程方法。

任务:定位子部件;感知窗口默认大小;感知窗口最小大小;改变大小处理;当内容改变时自动更新:

  • 字体大小,文本或子部件的其他内容随之改变;
  • 隐藏或显示子部件;
  • 移除一个子部件。

QBoxLayout(基本布局管理器)

  • QHBoxLayout(水平布局管理器):把子窗口从左到右排列在一个水平行上。
1
2
3
4
5
6
7
8
9
10
11
12
13
      QWidget *window = new QWidget;
      QPushButton *button1 = new QPushButton("One");
      QPushButton *button2 = new QPushButton("Two");
      QPushButton *button3 = new QPushButton("Three");
      QPushButton *button4 = new QPushButton("Four");
      QPushButton *button5 = new QPushButton("Five");
      QHBoxLayout *layout = new QHBoxLayout;
      layout->addWidget(button1);
      layout->addWidget(button2);
      layout->addWidget(button3);
      layout->addWidget(button4);
      layout->addWidget(button5);
      window->setLayout(layout);
  • QVBoxLayout(垂直布局管理器):把子窗口从上到下排列在一个垂直列上。
1
2
3
4
5
6
7
8
9
10
11
12
13
  QWidget *window = new QWidget;
  QPushButton *button1 = new QPushButton("One");
  QPushButton *button2 = new QPushButton("Two");
  QPushButton *button3 = new QPushButton("Three");
  QPushButton *button4 = new QPushButton("Four");
  QPushButton *button5 = new QPushButton("Five");
  QVBoxLayout *layout = new QVBoxLayout;
  layout->addWidget(button1);
  layout->addWidget(button2);
  layout->addWidget(button3);
  layout->addWidget(button4);
  layout->addWidget(button5);
  window->setLayout(layout);

QGridLayout(栅格布局管理器):把子窗口排列在一个二维的网格中,窗口可占据多个单元格。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    QWidget *window = new QWidget;
    QPushButton *button1 = new QPushButton("One");
    QPushButton *button2 = new QPushButton("Two");
    QPushButton *button3 = new QPushButton("Three");
    QPushButton *button4 = new QPushButton("Four");
    QPushButton *button5 = new QPushButton("Five");
    QGridLayout *layout = new QGridLayout;
    layout->addWidget(button1, 0, 0);
    layout->addWidget(button2, 0, 1);
    layout->addWidget(button3, 1, 0, 1, 2);
    layout->addWidget(button4, 2, 0);
    layout->addWidget(button5, 2, 1);
    window->setLayout(layout);
    window->show();

QFormLayout(窗体布局管理器):把子窗口按照标签-输入框的形式排列在两列。

QFormLayout将在一行上添加两个控件,通常是QLabel和QLineEdit。在同一行中添加QLabel和QLineEdit,将把QLineEdit设置为QLabel的伙伴。

1
2
3
4
5
6
7
8
9
10
11
12
13
    QWidget *window = new QWidget;
    QLabel *label1 = new QLabel("One");
    QLabel *label2 = new QLabel("Two");
    QLabel *label3 = new QLabel("Three");
    QLineEdit *line1 = new QLineEdit;
    QLineEdit *line2 = new QLineEdit;
    QLineEdit *line3 = new QLineEdit;
    QFormLayout *layout = new QFormLayout;
    layout->addRow(label1, line1);
    layout->addRow(label2, line2);
    layout->addRow(label3, line3);
    window->setLayout(layout);
    window->show();

QStackedLayout(栈布局管理器):无

8. QMainWindow框架包含的组件,QMainWindow各部件使用的编程方法。

QMainWindow类提供了一个应用程序主窗口,包括一个菜单栏( menu bar)、多个工具栏(tool bars)、多个锚接部件(dock widgets)、一个状态栏(status bar)以及一个中心部件(central widget)。

函数:

1
2
3
4
QMenuBar* QMainWindow::menuBar ( ) const;
QToolBar* QMainWindow::addToolBar ( const QString& title );
void QMainWindow::setCentralWidget ( QWidget* widget );
QStatusBar* QMainWindow::statusBar ( ) const;

程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    this->resize(1200, 800);

    QMenuBar *bar = new QMenuBar;
    this->setMenuBar(bar);

    //创建菜单,只能有一个
    QMenu *file = bar->addMenu("文件");
    QMenu *edit = bar->addMenu("编辑");
    QMenu *build = bar->addMenu("构建");

    //添加菜单项
    file->addAction("新建");
    file->addAction("打开");
    //添加分割线
    file->addSeparator();
    file->addAction("关闭");

    QToolBar *toolbar = new QToolBar(this);
    this->addToolBar(Qt::LeftToolBarArea, toolbar);
    toolbar->setAllowedAreas(Qt::RightToolBarArea | Qt::LeftToolBarArea);

    //设置浮动
    toolbar->setFloatable(false);

    //是否可移动,设置为否时工具栏固定不能动
    toolbar->setMovable(false);

    //工具栏添加内容
    toolbar->addAction("欢迎");
    toolbar->addAction("编辑");
    //添加分隔线
    toolbar->addSeparator();
    toolbar->addAction("设计");
    toolbar->addAction("调试");
    //添加按钮
    QPushButton * btn = new QPushButton("帮助",this);
    toolbar->addWidget(btn);

    //状态栏,最多有一个
    QStatusBar * stabar = new QStatusBar();
    //将状态栏添加到窗口
    this->setStatusBar(stabar);

    //添加标签控件
    QLabel * label_1 = new QLabel("问题",this);
    QLabel * label_2 = new QLabel("概要信息",this);
    QLabel * label_3 = new QLabel("右侧提示信息",this);
    stabar->addWidget(label_1);
    stabar->addWidget(label_2);

    //标签在右边显示
    stabar->addPermanentWidget(label_3);

    QTextEdit * qedit = new QTextEdit(this);
    this->setCentralWidget(qedit);

    //铆接部件,可以有多个
    QDockWidget * dock = new QDockWidget("浮动窗口",this);
    this->addDockWidget(Qt::BottomDockWidgetArea,dock);

    //设置后期停靠区域,只允许上下
    dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);

菜单栏:

QMenuBar类提供了一个水平的菜单栏,在QMainWindow中可以直接获取它的默认存在的菜单栏,向其中添加QMenu类型的菜单对象,然后向弹出菜单中添加QAction类型的动作对象。

工具栏:

工具栏QToolBar类提供了一个包含了一组控件的可以移动的面板,它用于提供常用命令或者选项的快速访问。

可以使用绝大多数窗口部件,最常用QToolButton和QComboBox。

使用addAction()添加部件。

中心部件:

在主窗口的中心区域可以放置一个中心部件,它一般是一个编辑器或者浏览器。这里支持单文档部件,也支持多文档部件。

采用Qt Designer创建主窗口时,默认情况下,系统已经创建了一个中心窗口部件,它是子类化QWidget的。

代码设置中心窗口部件可以调用主窗口类setCentralWidget()方法,每次程序调用setCentralWidget()方法时,先前存在的中心窗口部件将被新的所替换,而且主窗口会销毁原来的部件,无需用户处理。

从理论上来讲,任何继承自QWidget的类的派生类的实例,都可以作为中心窗口部件使用。

状态栏:

QStatusBar类提供了一个水平条,用来显示状态信息。

QMainWindow中默认提供了一个状态栏。在状态栏的最右端,还有一个QSizeGrip部件,用来调整窗口的大小,可以使用setSizeGripEnabled()函数来禁用它。

状态信息可以被分为三类:

临时信息,如一般的提示信息;使用showMessage()函数来显示一个临时消息,它会出现在状态栏的最左边。

正常信息,如显示页数和行号;一般用addWidget()函数添加一个QLabel到状态栏上用于显示正常信息,它会生成到状态栏的最左边,可能会被临时消息所掩盖。

永久信息,如显示版本号或者日期。如果要显示永久信息,要使用addPermanentWidget()函数来添加一个如QLabel一样的可以显示信息的部件,它会生成在状态栏的最右端,不会被临时消息所掩盖。

9. Qt对C++的一些扩展:Q_OBJECT、moc、uic

Q_OBJECT Qt中的元对象系统(Meta-Object System)提供了对象间通信的信号和槽机制、运行时类型信息和动态属性系统。元对象系统是基于以下三个条件的:

  1. 该类必须继承自QObject类;

  2. 必须在类的私有声明区声明Q_OBJECT宏(在类定义时,如果没有指定public或者private,则默认为private);

  3. 元对象编译器Meta-Object Compiler(moc),为QObject的子类实现元对象特性提供必要的代码。

moc工具读取一个C++源文件,如果它发现一个或者多个类的声明中包含有Q_OBJECT宏,便会另外创建一个C++源文件(就是在项目目录中的debug目录下看到的以moc开头的C++源文件),其中包含了为每一个类生成的元对象代码。这些产生的源文件或者被包含进类的源文件中,或者和类的实现同时进行编译和链接。

10. 为应用程序提供图片的常用方法(资源机制)

Qt资源机制是一个独立于平台的(跟使用的操作系统无关)用于在可执行文件中存储二进制文件的机制,是Qt核心机制之一。

可以让需要的文件(图片、文本等)包含到程序编程生成的可执行文件(例如exe文件)中。保证了程序中使用的文件不会丢失、不会因为存放路径而导致程序运行错误。

使用资源集( Resource Collection Files)文件,即.qrc文件。qmake能够识别这个资源集文件,并且能够根据它的描述去相应的目录下定位具体的资源 。

qrc资源文件是基于标准 xml 格式的文本文件,列出了所有嵌入到可执行文件中的文件 ,条理非常清晰,易于阅读和维护。

1
2
3
4
5
6
7
<RCC>
    <qresource>
        <file>images/new.png</file>
        <file>images/open.png</file>
        <file>images/save.png</file>
    </qresource>
</RCC>       

在这里指明了文件类型为RCC,表明是Qt资源文件。然后是资源前缀,应用程序中,资源是路径前缀识别的。file罗列了添加的图片的路径。

资源文件使用时,在工程文件.pro中添加一行代码:

RESOURCES += myImage.qrc

引用资源时,需要使用带路径前缀冒号斜线:/例如:

:/images/icon.png

11. 事件概念,继承QEvent类,几种常见的事件,鼠标事件(必会)和键盘事件,Qt中实现定时的方法。

定义:事件是对各种应用程序需要知道的由应用程序内部或者外部产生的事情或者动作的通称。

Qt中事件被封装成一个个对象,所有的事件均继承自抽象类QEvent。

Qt程序是事件驱动的, 程序的每个动作都是由幕后某个事件所触发。

Qt事件的发生和处理成为程序运行的主线,存在于程序整个生命周期。

当调用QApplication::exec()时,就进入了事件循环。

  • 键盘事件: 按键按下和松开.
  • 鼠标事件: 鼠标移动,鼠标按键的按下和松开.
  • 拖放事件: 用鼠标进行拖放.
  • 滚轮事件: 鼠标滚轮滚动.
  • 绘屏事件: 重绘屏幕的某些部分.
  • 定时事件: 定时器到时.
  • 焦点事件: 键盘焦点移动.
  • 进入和离开事件: 鼠标移入widget之内,或是移出.
  • 移动事件: widget的位置改变.
  • 大小改变事件: widget的大小改变.
  • 显示和隐藏事件: widget显示和隐藏.
  • 窗口事件: 窗口是否为当前窗口.

鼠标事件:

QMouseEvent类用来表示一个鼠标事件,当在窗口部件中按下鼠标或者移动鼠标指针时,都会产生鼠标事件。利用QMouseEvent类可以获知鼠标是哪个键按下了,还有鼠标指针的当前位置等信息。通常是重定义部件的鼠标事件处理函数来进行一些自定义的操作。

1
2
3
4
5
void mousePressEvent(QMouseEvent * event); //单击 
void mouseReleaseEvent(QMouseEvent * event); //释放 
void mouseMoveEvent(QMouseEvent * event); //移动  
void mouseDoubleClickEvent(QMouseEvent * event); //双击
void wheelEvent(QWheelEvent *event); //滑轮

添加头文件

1
#include <QMouseEvent>

键盘事件:

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

QKeyEvent的key()函数可以获取具体的按键,需要特别说明的是,回车键在这里是Qt::Key_Return;

键盘上的一些修饰键,比如Ctrl和Shift等,这里需要使用QKeyEvent的modifiers()函数来获取它们。

1
2
void keyPressEvent (QKeyEvent * event)
void keyReleaseEvent (QKeyEvent * event) 

添加头文件

1
#include <QKeyEvent

定时器:

QTimerEvent类:用来描述一个定时器事件。

startTimer (int interval):来开启一个定时器。

函数原型:

1
int QObject::startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer)

参数:设定定时时间ms

返回值:返回一个整型编号来代表这个定时器。

当定时器溢出时就可以在timerEvent()函数中获取该定时器的编号来进行相关操作

QTimer类:实现一个定时器,可以使用信号和槽实现定时操作,还可以设置只运行一次的定时器。

12. Qt中事件处理(最重要的两种方式)和事件过滤方法。

模式一:重新实现event()或部件处理函数。

重载event函数,实现一些不常见的功能或增加新功能;

重载部件处理函数,例如paintEvent(),mousePressEvent(),是最常用方式,处理特定部件的特定事件。

模式二:安装事件过滤器

在QApplication对象上安装全局事件过滤器,减缓事件传递;

在对象上安装事件过滤器,常用方式。

事件过滤器:Qt中一个独特的事件处理机制, 可以让一个对象侦听拦截另外一个对象的事件 ;

1)调用installEventFilter()注册需要管理的对象

2)在eventFilter() 里处理需要管理的对象的事件。

13. 位置函数的使用。图形的绘制方法(QPainter、paintEvent())

位置函数:Qt提供了很多关于获取窗体位置以及显示区域大小的函数,如x( )、y( )和pos( )、rect( )、size( )、geometry( )区别等。

QPainter完成具体的绘制操作,提供了大量函数来完成大部分绘制工作。例如:直线、曲线、圆形、弧形等,还可以用来绘制文本和图片。

QPainter可以在继承自QPaintDevice类的任何对象上进行绘制操作。

1
QPainter(QPaintDevice **device*)

QPainter一般在部件的绘图事件paintEvent()中进行绘制,首先创建QPainter对象,然后进行图形的绘制,最后记得销毁QPainter对象。当窗口程序需要升级或者重新绘制时,调用此成员函数。使用repaint()和update()后,调用函数paintEvent()。

重绘事件的处理函数 :paintEvent()

当窗口部件第一次显示时,系统会自动产生一个绘图事件。

repaint()与update()函数被调用时。

当窗口部件被其他部件遮挡,然后又再次显示出来时,就会对隐藏的区域产生一个重绘事件。

重新调整窗口大小时。

14. Qt文件接口QFile中输入输出方法以及相关类 文本文件和二进制文件读写操作。(代码)

QFile继承自QIODevice;

QFile是用来读写二进制文件、文本文件、资源文件的I/O设备。

文件名通常可以通过QFile构造函数来传递,但也可以使用setName()来设置。

QFile可以单独被使用,也可以和QDataStream或QTextStream一起使用将更加方便。

exists()来检查一个文件是否存在、remove()来移去一个文件。

用open()来打开、用close()来关闭、用flush()来刷新。

数据通常可以使用QDataStream或者QTextStream进行读写,但你也可以使用read()、readLine()、readAll()、write()读写。QFile也支持getChar(),putChar(),和ungetChar()

size()可以返回文件的大小。你可以通过使用pos()函数得到当前文件位置或者使用seek()移到一个新的文件位置。如果你到了文件的末尾,atEnd()返回真。

QTextStream 类:

QTextStream 也提供了一些用于格式化输出的描述符,这些描述符放置在输出内容之前,或者是使用相应的函数,用于对后面的输出内容做格式化。

QTextStream的格式化函数:

1
2
3
4
setIntegerBase(int); //设置进制,如0,2,8,10,16
qSetFieldWidth(int Width); //设置字段宽度
qSetPadChar(Qchar ch); //设置填充字符
qSetRealNumberPrecision(int precision); //设置实数精度

向文件写数据

1
2
3
4
5
6
7
8
9
10
    QFile file("test.txt");
    if (file.open(QFile::WriteOnly | QFile::Truncate)) //将原来文件内容清空
    {
        QTextStream out(&file);
        // 左对齐,占10个字符位置
        out << QObject::tr("成绩") << qSetFieldWidth(10) << left << 80 << endl;
        // 居中,占10个字符位置
        out << QObject::tr("成绩") << qSetFieldWidth(10) << center << 80 << endl;
    }
    file.close();

从文件读数据

  • readline()
  • readAll()
  • read(n)
  • seek()
1
2
3
4
5
6
7
8
    QFile file("test.txt");
    if (file.open(QFile::ReadOnly)) //将原来文件内容清空
    {
        QTextStream in(&file);
        QString str;
        str = in.readAll();
        qDebug() << str << endl;
    }

QDataStream类

QDataStream类提供了将二进制文件序列化的功能。

QDataStream类实现了C++基本数据类型的串行化,如char、short、int、char *等。

序列化写入

1
2
3
4
5
6
    QFile file("binary.dat");
    file.open(QIODevice::WriteOnly);
    QDataStream out(&file);
    out << QObject::tr("坐标");
    out << qint32(42) << qint32(96);
    file.close();

读取

1
2
3
4
5
6
7
8
    QFile file("binary.dat");
    file.open(QIODevice::ReadOnly);
    QDataStream in(&file);
    QString str;
    qint32 x, y;
    in >> str >> x >> y;
    qDebug() << str << x << y << endl;
    file.close();

15. Qt数据库

不用学

16. Qt数据库

不用学

17. Qt中与网络相关类(QNetworkAccessManager、QFtp、QHttp、QTcpSocketQUdpSocketQTcpServer

QNetworkAccessManager类:

网络操作的协同工作,允许应用程序发送网络请求和接收网络应答。一旦一个请求被创建,那么应用程序就可以使用它在网络上发送请求。它提供了一组标准的函数,可以承载网络请求和一些可选的数据,并且每一个请求返回一个QNetworkReply对象。该返回的对象包含着返回的请求应带的所有数据。

QHttp类:

文件下载是网络应用的常用功能,下面介绍如何实现基于HTTP协议的文件下载功能。具体实现步骤如下:

  1. 头文件httpclient.h的具体内容(第11章11.4-1.txt)。
  2. 源文件httpclient.cpp的

QTcpSocket 继承于QAbstractSocket继承于QIODevice,可以通过使用QTextStream和QDataStream来进行读取和写入。

1
2
3
4
5
6
7
8
9
10
11
peerAddress() //获取IP地址 peer指用TCP协议连接在一起的主机的通称
peerName() //获取名称
peerPort() //获取端口号
read() && write() //进行读写
bytesAvailable() //返回包的字节数,读数据之前,确保里面有数据
/*关联*/connect(Socket, SIGNAL(readyRead()), this, SLOT(readMessage())); //当有数据发送过来指定的套接字,便执行槽函数
close(); //套接字的关闭/服务器的关闭
// 发送数据时一定要在最开始写入实际数据大小信息(占两个字节) 用quint16表示
/*信号*/connected() //成功与服务器建立连接后产生的信号;readyRead ()有数据读信号;
bytesWritten() //数据成功发送后产生的信号;
error() //产生错误的信号;

QUdpSocket类:

服务器端建立一个UDP Socket并绑定在固定端口后,用信号与槽的方式进行监听是否有数据来临。

1
2
3
4
5
bind() //绑定IP地址和端口号
writeDatagram() //写数据报
readDatagram() //读数据报
hasPendingDatagrams() //判断是否有等待读取的数据报
pendingDatagramSize() //获取数据报大小

QTcpServer类:

1
2
3
4
5
6
7
8
listen() //监听连接
bool hasPendingConnections()const //如果服务端有一个待处理的连接,就返回真,否则返回假
QTcpSocket* nextPendingConnection() //返回一个套接字来处理一个连接,这个套接字作为服务端的一个子对象,意味着当QTcpServer对象销毁时候,这个套接字也自动删除,当使用完后明确的删除这个套接字也好,这样可以避免内存浪费。当没有可处理的连接时候,这个函数返回0。
serverAddress() //服务端的地址
serverPort() //服务器端口。
void setMaxPendingConnections(int numConnections) //设定待处理的连接最大数目为numConnections,当超过了最大连接数后,客户端仍旧可以连接服务端,但是服务端不在接受连接,操作系统会把这些链接保存在一个队列中。
close() //关闭套接字,停止对连接的监听。
newConnection() //信号

18. 线程概念及Qt相关类 线程的创建与启动。

QThread类提供了与系统无关的线程;

QThread代表在程序中一个单独的线程控制,在多任务操作系统中,它和同一进程中的其它线程共享数据,但运行起来就像一个单独的程序一样。它不是在main()中开始,QThread是在run()中开始运行的。

Run()对于线程的作用相当于main函数对于应用程序。它是线程的入口,run的开始和结束意味着线程的开始和结束。

创建线程一般步骤:

  1. 子类化线程
  2. 实现run函数,即线程功能
  3. 调用start函数,开始创建一个线程所需相关环境(例如堆栈空间,事件队列等),最后执行run函数。
  4. wait函数,清理线程。

线程启动

1
void start(Priority priority = InheritPriority)

调用后会执行run()函数,但在run()函数执行前会发射信号started(),操作系统将根据优先级参数调度线程。

程序设计 1.窗体添加按钮,实现退出功能,进行信号与槽的应用。

mainwindow.h

1
2
private slots:
    void tuichu();

mainwindow.cpp

1
2
3
4
5
6
7
8
9
10
11
12
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QPushButton *button1 = new QPushButton(this);
    button1->setText("exit");
    connect(button1, SIGNAL(clicked(bool)), this, SLOT(tuichu()));
}

void MainWindow::tuichu()
{
    this->close();
}

程序设计 2.主窗口创建动作、工具栏、菜单的程序代码。

1
2
3
4
5
6
7
8
9
10
11
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QAction *openAction = new QAction(tr("&Open"), this);
    openAction->setShortcut(QKeySequence::Open);  // 设置动作快捷键
    openAction->setStatusTip(tr("Open a file"));  // 状态栏显示
    QMenu *file = menuBar()->addMenu(tr("&File"));  // 把这个 QAction 添加到菜单
    file->addAction(openAction);
    QToolBar *toolBar = addToolBar(tr("&File"));  //把这个 QAction 添加到工具条:
    toolBar->addAction(openAction);
}

程序设计 3.窗体添加部件,并进行布局的关键代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    QWidget *window = new QWidget;
    QPushButton *button1 = new QPushButton("One");
    QPushButton *button2 = new QPushButton("Two");
    QPushButton *button3 = new QPushButton("Three");
    QPushButton *button4 = new QPushButton("Four");
    QPushButton *button5 = new QPushButton("Five");
    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(button1);
    layout->addWidget(button2);
    layout->addWidget(button3);
    layout->addWidget(button4);
    layout->addWidget(button5);
    window->setLayout(layout);
    window->show();

程序设计 4.文本文件和二进制文件读写操作。

文本读写1

1
2
3
4
5
6
7
8
9
10
    QFile file1("test1.txt");
    if(!file1.open(QFile::ReadWrite)){
        qDebug() << "fail";
        return;
    }
    QTextStream ts1(&file1);
    ts1 << QObject::tr("file1");  // 写
    ts1.seek(0);
    qDebug() << ts1.readAll();  // 读
    file1.close();

文本读写2

1
2
3
4
5
6
7
8
    QFile file3("test3.txt");
    if(!file3.open(QFile::ReadWrite)){
        qDebug() << "fail";
    }
    file3.write("file3");
    file3.seek(0);
    qDebug() << file3.readAll();
    file3.close();

二进制文件读写

1
2
3
4
5
6
7
8
9
10
11
    QFile file2("test2.txt");
    if(!file2.open(QFile::ReadWrite)){
        qDebug() << "fail";
    }
    QDataStream ds2(&file2);
    QString s;
    ds2 <<QString("file2");  // 写
    ds2.seek(0);
    ds2 >> s;  // 读
    qDebug() << s;
    file2.close();

程序设计 6.多窗口切换

1
2
3
4
5
6
7
8
9
10
11
12
13
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QPushButton *button = new QPushButton(this);
    button->setText("Show");
    connect(button, SIGNAL(clicked(bool)), this, SLOT(ShowWidget()));
}
void MainWindow::ShowWidget()
{
    QDialog *dia = new QDialog(this);
    dia->resize(300, 300);
    dia->show();
}

程序设计 7.多线程

workthread.h

1
2
3
4
5
6
class WorkThread : public QThread
{
    public:
    WorkThread();
    void run() override;
};

workthread.cpp

1
2
3
4
5
6
7
8
9
10
11
12
void WorkThread::run()
{
    while(true)
    {
        for(int i = 0; i < 10; i++)
        {
            qDebug() << i;
            sleep(2);
        }
        break;
    }
}

main.cpp

1
2
3
    WorkThread w1, w2;
    w1.start(QThread::HighPriority);
    w2.start(QThread::LowPriority);