QT多窗口编程与文件IO编程

2023-05-16

目录

一、消息对话框 QMessageBox(掌握)

二、常用窗口类(掌握)

三、主窗口类 QMainWindow(重点)

四、parent参数(掌握)

五、窗口传参

5.1 成员函数/构造函数

5.2 信号槽传参

六、事件机制(掌握)

一、文件选择对话框 QFileDialog(熟悉)

二、文件信息类 QFileInfo

三、文件读写类 QFile(掌握)

四、UI与耗时操作(掌握)

五、多线程 QThread(掌握)

5.1 线程的基本使用

5.2 异步刷新

5.3 关闭线程


一、消息对话框 QMessageBox(掌握)

之前的编程更多的是使用QDebug进行信息的输出,但是QDebug是调试信息,这些信息用户不可见,如果想给用户一些通知信息,使用消息对话框十分合适。

预设了四种消息对话框:

这种预设好的QDialog派生类往往具有一个共同的特点:弹窗使用一个静态成员函数。

如果只是简单弹窗,四种预设窗口的参数是相同的,如下所示:

参数1:依赖的父窗口

参数2:标题

参数3:展示的信息

返回值:枚举,表示用户点击的按键,只对question有意义

二、常用窗口类(掌握)

常用的窗口类继承结构如下所示:

QWidget类除了可以表示所有组件类的基类外,也是所有窗口类的基类,当QWidget构造函数的parent参数没有传递时,表示一个窗口对象;如果传递了,则表示一个组件对象。但是由于QWidget的继承层次比较高,实际开发过程中很少使用它的对象作为窗口和组件。

QWidget的直接派生类不光有对话框窗口类QDialog,还有主窗口类QMainWindow。对于大多软件而言,主窗口只有一个,建议使用QMainWindow,因为QMainWindow包含了菜单栏、工具栏、状态栏等。而QDialog无法胜任功能很多的软件的主窗口。

QWidget类作为所有窗口类的基类,内部也规定了很多窗口类共用的一些函数和属性,例如:

  • 设置窗口标题

void setWindowTitle(const QString &)

通过此函数设置windowTitle属性值,来更改窗口标题文字

  • 设置窗口图标

void setWindowIcon(const QIcon & icon)

通过此函数设置窗口的icon属性,来更改窗口的图标

  • 设置窗口标记

void setWindowFlags(Qt::WindowFlags type)

通过设置窗口标记的枚举值,让窗口达到某种视觉效果。

可以同时设定多个标记,如下所示。

setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint)

  • 设置窗口状态

void QWidget::setWindowState(Qt::WindowStates windowState)

通过设置窗口状态的枚举值,让窗口达到某种显示状态。

三、主窗口类 QMainWindow(重点)

QMainWindow表示主窗口类,因为相比QDialog,它多出了很多部分。本节课程创建的项目主窗口为QMainWindow。

1. 菜单栏 QMenuBar

菜单栏中的每个选项是一个菜单类QMenu对象

,这些对象属于菜单栏。

每个菜单中可以触发的选项被称为“动作”,类名为QAction。每个QAction对象可以通过Designer下方的Action编辑器来设置属性值。

QAction的属性常用属性设定如下:

QAction的常用信号如下:

2. 工具栏 QToolBar

在Designer中,直接把Action编辑器中的QAction拖动到工具栏即可。

3. 中心组件 QWidget

中心组件相当于之前QDialog的内容,用于设计窗口中主要展示的内容。

4. 状态栏 QStatusBar

使用槽函数可以显示或清除状态栏信息。

void QStatusBar::showMessage(const QString & message, int timeout = 0) [slot]

展示信息

参数1:要展示的文字

参数2:显示的时长,参数为毫秒,默认值为持续显示

void QStatusBar::clearMessage() [slot]

清除信息

四、parent参数(掌握)

parent参数除了表示组件与窗口的之间从属关系外,parent参数还能有效地防止内存泄露。所有子组件和子窗口都会等待父窗口销毁时,一并销毁。

下面的例子,自定义一个Qt的窗口类,步骤如下:

1. 在Qt Creator中,选中项目名称,鼠标右键,点击“添加新文件”。

2. 在弹出的窗口中,按照下图所示进行操作。

3. 在弹出的窗口中,配置窗口的相关信息。

4. 在弹出的窗口中,填写类名,点击“下一步”。

5. 在项目管理页面,直接点击完成。可以看到项目中多了一个窗口类的相关文件。

五、窗口传参

5.1 成员函数/构造函数

【例子】有两个窗口(A启动B),在窗口A中转动QDial,窗口B中的另一个QDial跟随转动。

5.2 信号槽传参

【例子】有两个窗口(A启动B),在窗口B中转动QDial,窗口A中的另一个QDial跟随转动。

六、事件机制(掌握)

事件机制是Qt一个核心机制,一些操作可以层层传递,程序员可以在传递的任何一个环节中,捕捉到这个事件并进行处理,不同于信号槽的是,它的使用不需要建立连接。

下图是某事件,从操作系统内核到窗口类的传递过程。

常见的事件对应的处理函数有:

void QWidget::paintEvent(QPaintEvent * event) [virtual protected]

绘制事件函数

void QWidget::resizeEvent(QResizeEvent * event) [virtual protected]

大小改变

void QWidget::mousePressEvent(QMouseEvent * event) [virtual protected]

鼠标按压

void QWidget::mouseReleaseEvent(QMouseEvent * event) [virtual protected]

鼠标释放

void QWidget::mouseDoubleClickEvent(QMouseEvent * event) [virtual protected]

鼠标双击

void QWidget::mouseMoveEvent(QMouseEvent * event) [virtual protected]

鼠标移动

void QWidget::moveEvent(QMoveEvent * event) [virtual protected]

自身移动

void QWidget::keyPressEvent(QKeyEvent * event) [virtual protected]

按键按下

void QWidget::keyReleaseEvent(QKeyEvent * event) [virtual protected]

按键释放

void QWidget::focusInEvent(QFocusEvent * event) [virtual protected]

获取焦点

void QWidget::focusOutEvent(QFocusEvent * event) [virtual protected]

失去焦点

void QWidget::closeEvent(QCloseEvent * event) [virtual protected]

关闭

void QWidget::enterEvent(QEvent * event) [virtual protected]

鼠标进入

void QWidget::leaveEvent(QEvent * event) [virtual protected]

鼠标离开

事件函数的使用步骤如下所示:

1. 查阅文档,确定要使用的事件函数,如:

void QWidget::paintEvent(QPaintEvent * event) [virtual protected]

2. 在头文件中声明事件函数

3. 在源文件中定义(覆盖)事件函数。

4. 在事件函数的函数体中写当前事件触发后执行的逻辑。

一、文件选择对话框 QFileDialog(熟悉)

与QMessageBox一样,QFileDialog也继承自QDialog,表示一个文件读写的选择对话框,这类对话框往往都是通过静态成员函数打开,并且返回值是用户选择的内容。

QFileDialog的常用静态成员函数,如下所示。

函数功能:获取一个读/写的文件路径

参数1:parent参数

参数2:窗口标题

参数3:在哪个路径打开(默认值为工作目录)

参数4:文件类型过滤器

返回值:选中的文件路径,如果用户不选择,则返回“”

二、文件信息类 QFileInfo

获取某一个文件的信息,一个不存在的路径也能创建出对应的QFileInfo对象,但是这样的对象调用exists函数,返回值是false

/**
 * @brief Dialog::printFileInfo 打印文件信息
 * @param path 文件路径
 * @param browser 显示的组件
 */
void Dialog::printFileInfo(QString path, QTextBrowser * browser)
{
    // 创建文件信息类对象
    QFileInfo info(path);
    // 获得创建的日期
    QString time = info.created().toString("yyyy-MM-dd hh:mm:ss");
    browser->append(time);

    if(info.isReadable())
        browser->append("可读");
    else
        browser->append("不可读");

    // 获取文件大小
    qint64 size = info.size();
    QString text;
    text.setNum(size).append("字节");
    browser->append(text);
}

三、文件读写QFile(掌握)

QFile类专用于文件的读写,其间接基类是QIODevice,QIODevice类是Qt中所有读写类的基类,内部规定了很多IO的相关基础框架。

QFile类用完即可释放,使用栈内存对象即可,因此也不需要parent参数的传递,构造函数只需要传递文件路径即可。

常用的函数如下:

bool QFile::open(OpenMode mode) [virtual]

以不同的模式打开文件,返回值是打开的结果。

virtual bool atEnd() const

判断是否读取到文件尾

QByteArray QIODevice::read(qint64 maxSize)

读取,参数为最大的字节数,返回值是读取好的字节数组对象

qint64 QIODevice::write(const QByteArray & byteArray)

写出,参数是写出的内容,返回值是实际写出的字节数,出错返回-1

四、UI与耗时操作(掌握)

在默认的情况,Qt只有一个线程,这个线程的主要作用是保证程序的正常执行(事件、信号槽、UI显示、UI交互等),被称为“主线程”或“UI线程”。

但是一些耗时操作(文件读写、网络通信等),如果主线程中执行耗时操作,会导致正常的UI相关操作被阻塞,程序UI出现卡顿、假死的情况。此时如果尝试关闭程序,关闭的命令也会被阻塞,操作系统发现某个程序关闭响应不及时执行,操作系统会弹出来引导用户是否强行关闭。

五、多线程 QThread(掌握)

5.1 线程的基本使用

QThread类是Qt中的线程类,常用函数如下:

void msleep(unsigned long msecs) [static]

让当前线程休眠一定的毫秒数

开启线程的步骤:

1. 在Qt Creator中,选中项目名称,鼠标右键,点击添加新文件。

2. 在弹出的窗口中,按照下图所示进行操作。

3. 依次按照下图所示输入类名、基类名、类型信息后,点击“下一步”。

4. 在项目管理界面,直接点击“完成”。可以看到在项目结构中多了线程类相关的文件。

5. QThread类中有一个void QThread::run() [virtual protected]函数,在自定义线程类中覆盖此函数。

6. 在run函数的函数体中,编写子线程要执行的代码。

7. 在主线程中创建子线程对象后,调用void QThread::start(Priority priority = InheritPriority) [slot]函数启动子线程,此时程序会出现两个执行的线程分支。

5.2 异步刷新

在实际的开发中,经常会遇见以下需求:

在子线程中执行耗时操作,在主线程中执行UI操作,但是主线程的UI操作需要根据子线程的执行情况进行刷新。

此时可以使用信号槽的方式进行线程通信。

需要注意的是,主线程不要执行耗时操作,子线程不要执行UI操作。

5.3 关闭线程

如果一个线程在运行的过程中被强行关闭会出现:

上面的情况说明,线程还咋运行突然被终止。我们应该保证线程先停止。

介绍两种停止线程的方式:

1. terminate

简单粗暴,但是是否即刻停止取决于调度。

2. interrupt

相对温和,内部通过标志位退出。

bool QThread::isInterruptionRequested() const

返回当前线程是否被请求终止。

需要注意的是,线程的run函数执行完也会自动停止。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT多窗口编程与文件IO编程 的相关文章

随机推荐