赞
踩
Qt提供了一个与平台无关的QProcess类,用以对进程的支持。本节讲述了怎样在Qt应用程序中启动一个外部程序进程,以及几种常用的进程间通信方法。
设计应用程序时,有时不希望将一个不太相关的功能集成到程序中,或者是因为该功能与当前设计的应用程序联系不大,或者是因为该功能已经可以使用现成的程序很好地实现了,这时就可以在当前的应用程序中调用外部的程序来实现该功能,这就会使用到进程。Qt应用程序可以很容易地启动一个外部应用程序,而且Qt也提供了多种进程间通信的方法。
本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓
Qt的QProcess类可以用来启动一个外部程序并与其进行通信。下面我们来看一下怎么在Qt代码中启动一个进程。
运行一个进程打开记事本
首先创建QtGui应用,工程名称为“myProcess”,其他选项保持默认即可。先进入mainwindow.h文件添加代码,添加私有对象定义:QProcess myProcess。然后在设计模式往界面上拖入一个Push Button部件,修改其显示文本为“启动一个进程”。在按钮上点击鼠标右键,转到其clicked()信号对应的槽,更改如下:
- void MainWindow::on_pushButton_clicked()
- {
- myProcess.start("notepad.exe");
- }
这里我们使用QProcess对象运行了Windows系统下的记事本程序(即notepad.exe程序),因为该程序在系统目录中,所以这里不需要指定其路径。大家也可以运行其他任何的程序,只需要指定其具体路径即可。我们看到,可以使用start()来启动一个程序,有时启动一个程序时需要指定启动参数,这种情况在命令行启动程序时是很常见的。
运行程序,单击界面上的按钮时就会弹出一个记事本程序。
QProcess也提供了一组函数,可以脱离事件循环来使用,它们会挂起调用的线程直到确定的信号被发射:
Qt提供了多种方法在Qt应用程序中实现进程间通信IPC(Inter-Process Communication)。 简单介绍如下 :
TCP/IP
跨平台的Qt Network模块提供的类可以让网络编程更加便携和方便。它提供了高级类(例如:QNetworkAccessManager、QFtp)通信,使用特定的应用程序级协议,和较底层的类(例如:QTcpSocket、QTcpServer、QSslSocket)用于实现协议。
共享内存
跨平台的QSharedMemory-共享内存类,提供对操作系统的共享内存的实现。它允许多个线程和进程安全访问共享内存段。此外,QSystemSemaphore可以用来控制访问由系统共享的资源,以及进程之间的通信。
D-Bus
Qt的D-Bus模块是一种可用于使用D-Bus协议实现IPC的唯一Unix库。它将Qt的信号和槽机制延伸到IPC级别,允许由一个进程发出的信号被连接到另一个进程的槽。Qt的D-Bus文档已经详细说明如何使用Qt中的D-Bus模块。
QProcess
使用先前提到的QProcess类。跨平台类QProcess可以用于启动外部程序作为子进程,并与它们进行通信。它提供了用于监测和控制该子进程状态的API。另外,QProcess为从QIODevice继承的子进程提供了输入/输出通道。
会话管理
在Linux/X11平台上,Qt提供了会话管理的支持。会话允许事件传播到进程,例如,当检测到关机时。进程和应用程序可以执行任何必要的操作,例如:保存打开的文档。
下面来看一个使用共享内存的例子,它实现的功能是:先在一个对话框中将一张图片写入到共享内存段中,然后再在另一个对话框中从共享内存段读出该图片。
新建Qt Gui应用,名称为mylPC,类名为Dialog,基类选择QDialog。完成后进人设计模式,向界面中放入两个Push Button部件和一个Label部件。将一个按钮的显示文本更改为“从文件中加载图片”,将其objectName属性更改为loadFromFileButton,将另一个按钮的显示文本更改为“从共享内存显示图片”,将其objectName属性更改为loadFromSharedMemoryButton。然后进人dialog.h文件,修改如下:
- #ifndef DIALOG_H
- #define DIALOG_H
-
- #include <QDialog>
- #include <QSharedMemory>
-
- namespace Ui {
- class Dialog;
- }
-
- class Dialog : public QDialog
- {
- Q_OBJECT
-
- public:
- explicit Dialog(QWidget *parent = nullptr);
- ~Dialog();
-
- public slots:
- //从文件中加载图片到共享内存
- void loadFromFile();
-
- //从共享内存中加载图片
- void loadFromMemory();
-
- private slots:
- //从文件中加载图片按钮
- void on_loadFromFileButton_clicked();
-
- //从共享内存加载并显示图片按钮
- void on_loadFromSharedMemoryButton_clicked();
-
- private:
- //将进程与共享内存段进行分离,如果失败则进行提示
- void detach();
-
- private:
- Ui::Dialog *ui;
-
- QSharedMemory sharedMemory; //定义一个共享内存对象
- };
-
- #endif // DIALOG_H
然后进人dialog.cpp文件,修改如下:
- #include "dialog.h"
- #include "ui_dialog.h"
-
- #include <QFileDialog>
- #include <QBuffer>
- #include <QDebug>
-
- Dialog::Dialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::Dialog)
- {
- ui->setupUi(this);
-
- //在使用共享内存以前,需要设置key,系统用它作为底层共享内存段的标识
- sharedMemory.setKey("QSharedMemoryExample");
- }
-
- Dialog::~Dialog()
- {
- delete ui;
- }
-
- //从文件中加载图片到共享内存
- void Dialog::loadFromFile()
- {
- //判断该进程是否已经连接到共享内存段,连接成功返回true
- if (sharedMemory.isAttached())
- detach();
-
- ui->label->setText(tr("选择一个图片文件!"));
- //使用文件对话框获得打开图片路径
- QString fileName = QFileDialog::getOpenFileName(nullptr, QString(), QString(),
- tr("Images (*.png *.jpg)"));
-
- //label标签显示图片
- QImage image;
- if (!image.load(fileName))
- {
- ui->label->setText(tr("选择的文件不是图片,请选择图片文件!"));
- return;
- }
- ui->label->setPixmap(QPixmap::fromImage(image));
-
- //将图片加载到共享内存
- //使用QBuffer来暂存图片,这样便可以获得图片的大小,还可以获得图片数据的指针
- QBuffer buffer;
- buffer.open(QBuffer::ReadWrite);
- QDataStream out(&buffer);
- out << image;
- int size = static_cast<int>(buffer.size());
- //使用create()函数创建指定大小的共享内存段,该函数还会自动将共享内存段连接到本进程上。
- if (!sharedMemory.create(size))
- {
- ui->label->setText(tr("无法创建共享内存段!"));
- return;
- }
-
- //在进行共享内存段的操作前,需要先进行加锁
- sharedMemory.lock();
- char *to = static_cast<char*>(sharedMemory.data());
- const char *from = buffer.data().data();
- //使用memcpy()函数将图片数据复制到共享内存
- memcpy(to, from, static_cast<size_t>(qMin(sharedMemory.size(), size)));
- //等操作完成后,再进行解锁。
- sharedMemory.unlock();
- }
-
- //从共享内存中加载图片
- void Dialog::loadFromMemory()
- {
- //使用attache()函数将进程连接到共享内存段
- if (!sharedMemory.attach())
- {
- ui->label->setText(tr("无法连接到共享内存段,\n"
- "请先加载一张图片!"));
- return;
- }
-
- QBuffer buffer;
- QDataStream in(&buffer);
- QImage image;
-
- //使用QBuffer来读取共享内存段中的数据
- sharedMemory.lock();
- buffer.setData((char*)sharedMemory.constData(), sharedMemory.size());
- buffer.open(QBuffer::ReadOnly);
- in >> image;
- sharedMemory.unlock();
-
- //将进程与共享内存段进行分离,如果失败则进行提示
- sharedMemory.detach();
- ui->label->setPixmap(QPixmap::fromImage(image));
- }
-
- //将进程与共享内存段进行分离,如果失败则进行提示
- void Dialog::detach()
- {
- if (!sharedMemory.detach())
- ui->label->setText(tr("无法从共享内存中分离!"));
- }
-
- //从文件中加载图片按钮
- void Dialog::on_loadFromFileButton_clicked()
- {
- loadFromFile();
- }
-
- //从共享内存加载并显示图片按钮
- void Dialog::on_loadFromSharedMemoryButton_clicked()
- {
- loadFromMemory();
- }
在一个运行的实例上单击“从文件中加载图片”按钮,然后选择一张图片。在第二个运行的实例上单击“从共享内存显示图片”按 钮,这时便会显示第一个实例中加载的图片,效果如下所示:
(1)loadFromFile()
(2)loadFromMemory()
本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。