Qt中的线程编程
在基于操作系统的程序设计中,在处理多任务时,可以有多种方法,但效率较高的当属线程方式,下面就来讨论一下在Qt中如何实现线程编程。
先来说一下什么是线程。线程(thread)是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位,一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈,自己的寄存器环境,自己的线程本地存储。在多核或多CPU,或支持Hyper-threading的CPU上使用多线程程序设计的好处是显而易见,即提高了程序的执行吞吐率。在单CPU单核的计算机上,使用多线程技术,也可以把进程中负责I/O处理、人机交互而常被阻塞的部分与密集计算的部分分开来执行,从而提高了程序的执行效率。
下面就以一个时钟显示的程序来说明在Qt中如何使用线程。在时间显示中,由于显示需要重复不断地刷新,所以可把它放在一个线程中,以节约主线程的资源。本程序基于Qt4.8.7版本制作,程序运行后的界面如下所示。
制作的具体过程如下:
1、启动Qt Creator开发环境,然后点击“New Project”新建项目,会弹出如下所示的对话框。
2、按上图中的默认选项,点击“Choose...”按钮,会弹出下面的对话框。
3、在上图的对话框中,可设置项目的名称和存储的位置,可按自己要求更改或按默认值(注意路径中不要包含中文),点击“下一步”按钮,出现下面的界面。
4、上面的界面为已配置好的环境,可直接点击“下一步”按钮,出现下面的界面。
5、在以上对话框中,可更改项目的细节,可按自己要求更改或按默认值,点击“下一步”按钮,出现下面的界面。
6、在图中直接点击“完成”按钮,结束项目新建的过程,最后得到如下图所示的开发环境。
7、在上图中,单击“项目”中的最后一项“界面文件”左边的箭头,展开该项的内容,然后双击其下的名为“mainwindow.ui”的界面文件,会打开界面设计窗口,如下图所示。
8、在设计界面中,默认有一个空的窗体,现在在左边的控件框中往下找到“Display Widgets”类,然后在其下找到“LCD Number”控件,并把它拖曳至窗体的中央,把长度设置为200像素,高度为60像素,如下图所示。
9、上述设计完成后,点击最左边工具条上的“编辑”切换到程序设计界面,展开“源文件”项,双击主窗体文件“mainwindow.cpp”把它打开,如下图所示。
10、在主程序中,加入对显示控件“LCD Number”的配置,修改后的主函数如下所示:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->lcdNumber->setDigitCount(8); //设置lcd里面的个数,格式是hh:mm:ss,总的是八个。所以设置为8
ui->lcdNumber->setFixedSize(220, 60); //设置大小
ui->lcdNumber->setPalette(Qt::cyan); //设置颜色
ui->lcdNumber->setSegmentStyle(QLCDNumber::Flat); //设置LCD字符为平面显示,无立体感
ui->lcdNumber->setStyleSheet("border: 1px solid black; color: black; background: silver;"); //设置LCD样式
TimeshowThread = new timeshowThread; //新建时间处理线程
connect(TimeshowThread, SIGNAL(sendTime(QString)), this, SLOT(displayTime(QString))); //连接时间显示槽函数
TimeshowThread->start(); //启动线程
}
11、然后加入一个新的函数,内容如下:
void MainWindow::displayTime(QString time) //时间显示槽函数
{
ui->lcdNumber->display(time);
}
12、改好的主程序界面如下所示。
13、 接下来点击“项目”中的“头文件”左边箭头展开该项,双击头文件“mainwindow.h”把它打开,如下图所示。
14、在上述头文件中,加入时间显示槽函数的申明,修改后的头文件如下所示:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "timeshowthread.h" //新加入线程程序的头文件
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
timeshowThread *TimeshowThread; //新建时间显示线程
private slots:
void displayTime(QString); //新加入的槽函数申明
};
#endif // MAINWINDOW_H
15、接下来要新建线程文件,在左边的“源文件”上点击右键,选择“添加新文件...”一项,会弹出如下图的对话框。
16、在上图中选择“C++Source File”一项,然后点击“Choose...”按钮,会弹出如下对话框。
17、在上图中填入新建的线程程序文件名称,这里填入“timeshowthread”,然后点击“下一步”按钮,会弹出如下对话框。
18、在上图中点击“完成”按钮,得到的界面如下所示。
19、在线程文件timeshowthread.cpp中加入以下内容:
#include "timeshowthread.h"
#include <QTime>
timeshowThread::timeshowThread()
{
}
void timeshowThread::run() //线程程序
{
while(1)
{
QDateTime current_date_time = QDateTime::currentDateTime(); //获取当前时间
QString current_time = current_date_time.toString("hh:mm:ss"); //格式化
emit sendTime(current_time); //发射信号
msleep(20); //延时
}
}
20、接下来新建线程头文件,在左边的“头文件”上点击右键,选择“添加新文件...”一项,会弹出如下图的对话框。
21、在上图中选择“C++Header File”一项,然后点击“Choose...”按钮,会弹出如下对话框。
22、在上图中填入新建的线程程序头文件名称,这里填入“timeshowthread”(要与线程程序名称一致),然后点击“下一步”按钮,会弹出如下对话框。
23、在上图中点击“完成”按钮,得到的界面如下所示。
24、在线程头文件timeshowthread.h中加入以下内容:
#ifndef TIMESHOWTHREAD_H
#define TIMESHOWTHREAD_H
#include <QThread>
#include <QString>
class timeshowThread : public QThread
{
Q_OBJECT
public:
timeshowThread(); //申明线程函数
signals:
void sendTime(QString); //申明信号发送函数
protected:
void run(); //申明线程执行函数
public slots:
};
#endif // TIMESHOWTHREAD_H
25、保存所有文件,点击运行按钮运行程序,将得到如前面所示的时钟界面。(注:程序能否正常运行还取决于开发环境的配置)
接下来简要说明一下线程的创建原理。
在Qt中提供有QThread类,要创建一个新的线程,只需定义一个类(如上述头文件timeshowthread.h中定义的timeshowThread),让其继承QThread类即可。然后使用自己创建的类(如timeshowThread)实例化一个对象,也就是用该类创建一个变量(如上述头文件mainwindow.h中的timeshowThread *TimeshowThread;一句及主程序文件mainwindow.cpp中的TimeshowThread = new timeshowThread;一句)。在QThread类中有一个虚函数QThread::run(),要实现自己的线程代码只需要重写该函数即可。最后,通过QThread类中的start()函数可启动这个线程(如TimeshowThread->start();)。另外,由于本例中只进行时间的显示一个任务,所示没有线程结束的操作,时间显示线程将同主线程(UI线程)一起结束。若要进行线程结束的操作,可执行“TimeshowThread->terminate();”即可。
在上面的例子中,还定义了一个信号sendTime(QString)和一个槽函数displayTime(QString time),并把两个量联系在一起(执行connect(TimeshowThread, SIGNAL(sendTime(QString)), this, SLOT(displayTime(QString)));一句)。这样一来, 当在线程中获取了当前时间量后,通过执行“emit sendTime(current_time);”一句,把当前时间量通过信号发送给槽函数displayTime,然后在槽函数中进行显示(执行ui->lcdNumber->display(time);一句)。在线程程序中,通过死循环来不断更新获取当前的时间量,并通过信号发送给槽函数进行显示,这样一来,由于死循环放在了线程中,并不会拖累主线程。但是,虽然死循环放在线程中,但也不能执行的太“满”,否则还是会占用过多的CPU资源,所以在上面的实例中,还是进行了一定时间的休眠(如执行msleep(20);一句)。这里要强调一点,具体休眠多长时间应根据实际的运行情况而定,因为线程通过操作系统来调度,所以休眠时间并不精确,并且休眠时间应以不过度消耗CPU资源为佳(当然,在此例中,由于时间以秒来更新,所以休眠最长可取1秒)。
Qt中的线程编程的更多相关文章
- QT中的SOCKET编程(QT-2.3.2)
转自:http://mylovejsj.blog.163.com/blog/static/38673975200892010842865/ QT中的SOCKET编程 2008-10-07 23:13 ...
- Qt中暂停线程的执行(主线程和工作线程共用一把锁,一旦主线程将它锁上,工作线程就无法运行了,这也是一个办法)
在线程中定义一个信号量: QMutex pause; 把run()函数中循环执行的部分用信号量pause锁住: void run() { while(1) { pause.lock ...
- QT中的SOCKET编程
转自:http://mylovejsj.blog.163.com/blog/static/38673975200892010842865/ QT中的SOCKET编程 2008-10-07 23:13 ...
- Qt中的多线程编程
http://www.ibm.com/developerworks/cn/linux/l-qt-mthrd/ Qt 作为一种基于 C++ 的跨平台 GUI 系统,能够提供给用户构造图形用户界面的强大功 ...
- Qt入门(9)——Qt中的线程支持
Qt对线程提供了支持,基本形式有独立于平台的线程类.线程安全方式的事件传递和一个全局Qt库互斥量允许你可以从不同的线程调用Qt方法.警告:所有的GUI类(比如,QWidget和它的子类),操作系统核心 ...
- QT中的线程与事件循环理解(2)
1. Qt多线程与Qobject的关系 每一个 Qt 应用程序至少有一个事件循环,就是调用了QCoreApplication::exec()的那个事件循环.不过,QThread也可以开启事件循环.只不 ...
- QT中的线程与事件循环理解(1)
1.需要使用多线程管理的例子 一个进程可以有一个或更多线程同时运行.线程可以看做是“轻量级进程”,进程完全由操作系统管理,线程即可以由操作系统管理,也可以由应用程序管理.Qt 使用QThread 来管 ...
- Qt中的串口编程之三
QtSerialPort 今天我们来介绍一下QtSerialPort模块的源代码,学习一下该可移植的串口编程库是怎么实现的. 首先,我们下载好了源代码之后,使用QtCreator打开整个工程,可以看到 ...
- Qt中暂停线程的执行
在线程中定义一个信号量 QMutex pause; 把run()函数中循环执行的部分用信号量pause锁住: void run() { while(1) { pause.lock(); //循环执行的 ...
- Qt中暂停线程的执行(利用QMutex,超级简单明了)
在线程中定义一个信号量: QMutex pause;把run()函数中循环执行的部分用信号量pause锁住: void run() { while(1) { pause.lock(); //循环执行的 ...
随机推荐
- 两步解决php超时问题
tp的报错很模糊,需要自己判断是不是超时问题 首先给Apache的配置文件httpd.conf添加几行: <IfModule mod_fcgid.c> FcgidProcessLifeTi ...
- disabled属性的简介和使用
一.disabled属性的简介和使用 Html中的input元素.button元素.option元素等都具有一个disabled属性. disabled对a标签不起作用当赋予该属性时该元素将变得不可交 ...
- 2022-06-01内部群每日三题-清辉PMP
1.采购部门要求项目经理提供一个项目的招标文件.这些文件中应该包含哪些内容? A.变更请求 B.选择的卖方 C.质量测量指标 D.建议邀请书 2.作为一个大型组织中关键项目的组成部分,阀门制造业务被外 ...
- Excel列动态导出
列动态导出的Excel,大致整了一下,没有过多深入. 1.首先定义列样式 package a.b.common.util.excel.stream; import java.util.Objects; ...
- echarts:双y轴图表刻度均匀分布问题
今天分享一个小问题,内容不多. 双y轴图表中,为了图表的美观,经常会隐藏一侧的y轴刻度线,仅显示一侧的刻度线.那么问题就来了,两个y轴的数据数值大小不同,常常会导致刻度线的刻度分布不均匀,该如何解决呢 ...
- mysql(insert + str_to_date)
str_to_date(date_str, '%Y-%m-%d %H:%i:%s') 替换为 substring_index(date_str, '.', 1); str_to_date(date_s ...
- [2] Bert 论文精读
BERT是NLP领域让预训练这件事情出圈的工作. 开篇Introduction介绍了两类主流的预训练方法: 1.feature-based,即基于特征的,即我首先通过预训练得到一些比较好的特征,然后将 ...
- 在百度云服务器上部署Django网站的经历
前言: 前段时间,利用Django为单位制作了一个小型的内部考勤系统,本想放到单位内部的服务器上,考虑到运行的稳定.安全防护等问题,最终决定把网站部署到百度云服务器上,事先也在网上查找了一些资料,但过 ...
- 掌控安全学院SQL注入靶场-布尔盲注(一)
靶场地址:http://inject2.lab.aqlab.cn/Pass-10/index.php?id=1 判断注入点: http://inject2.lab.aqlab.cn/Pass-10/i ...
- geoserver的自动化部署
年后接到一个任务,需求是这样的: 搭建一个geoserver服务器,将公司内部的mbtile数据(EPSG:3857)发布出去 服务的输出格式为MBTiles with vector tiles的矢量 ...