Qt QProcess详解

1.简介

QProcess提供了在 Qt 应用程序中启动外部程序的方法。通过QProcess,你可以启动一个进程,与它通信(发送输入和读取输出),检查它的状态,以及等待它完成。这个类在执行系统命令、运行其他程序或脚本时非常有用。

2.基本使用

  • 启动进程: 使用start()、execute()、或startDetached()方法来启动一个进程,后面讲解区别。
  • 读取输出:使用readAllStandardOutput()和 readAllStandardError()方法来读取进程的标准输出和标准错误输出。
  • 进程状态: 使用state()方法来检查进程的状态,例如是否正在运行、是否已结束等。
  • 等待进程完成: 使用 waitForFinished()方法等待进程结束。也可以使用 exitCode()和exitStatus()方法来检查进程的退出码和退出状态。
  • 终止进程:使用kill()和terminal()来终止进程。

3.信号和槽

QProcess提供了一些信号,可以在特定事件发生时发出,例如:

  • started: 进程开始执行时发出。
  • readyReadStandardOutput: 进程的标准输出有数据可读时发出。
  • readyReadStandardError: 进程的标准错误输出有数据可读时发出。
  • finished: 进程结束时发出。
QProcess process;
process.start("ls", QStringList() << "-l" << "/home/user");

connect(&process, &QProcess::readyReadStandardOutput, [&]() {
    qDebug() << "Standard output:" << process.readAllStandardOutput();
});

connect(&process, &QProcess::readyReadStandardError, [&]() {
    qDebug() << "Standard error:" << process.readAllStandardError();
});

connect(&process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
          [=](int exitCode, QProcess::ExitStatus exitStatus)
{
    qDebug() << "Process finished with exit code" << exitCode<<" "<<exitStatus;
});

4.启动进程的区别

  • start()

    • start方法用于启动一个外部程序,它是异步的,意味着它会在启动进程后立即返回,不会阻塞调用线程。
    • 使用start,你可以与进程交互,例如读取输出、写入输入、等待进程完成等。
    • 可以指定进程的参数、环境变量,并且可以选择性地重定向标准输入输出。
    • start方法适用于需要与启动的进程进行通信或需要监控进程状态的情况。
  • execute()

    • execute方法也是用于启动一个外部程序,但它是以同步方式进行的,会阻塞调用线程直到外部程序执行完毕。
    • execute在内部调用start,然后等待进程结束,并返回进程的退出代码。
    • 由于它是同步的,execute不适合需要与进程交互或不想阻塞主线程的应用程序。
    • execute不提供重定向标准输入输出的选项,也不允许在进程运行期间执行其他任务。
    • execute的使用比较简单,因为它会自动等待进程结束,并且返回退出代码。
  • startDetached()

    • startDetached方法用于在独立的进程中启动一个外部程序,它与父进程完全分离,不与父进程的QProcess实例进行通信,(这意味着无法使用信号-槽通信)。
    • startDetached 适用于启动那些不需要与父进程交互的独立应用程序。
    • 使用 startDetached启动的进程有自己的控制台窗口(在 Windows 上),而 start和 execute启动的进程通常与父进程共享控制台。
    • startDetached不需要父进程等待子进程结束,子进程可以在父进程退出后继续运行。

5.示例

示例1:打开记事本程序。

源码:

说明:这里打开记事本程序,绑定了三个信号,使用start的方式打开,因为是异步的方式,所以父程序和记事本程序都可以操作。如果关闭了父程序,记事本程序会跟着关闭。

如果使用waitForFinished方法,就只能操作子程序,会在子程序结束后才能够操作父程序。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QProcess>
#include <QDebug>

// 创建 QProcess 对象
QProcess *process = nullptr;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    process = new QProcess(this);

    connect(process, &QProcess::readyReadStandardOutput, [&]() {
        qDebug() << "Standard output:" << process->readAllStandardOutput();
    });

    connect(process, &QProcess::readyReadStandardError, [&]() {
        qDebug() << "Standard error:" << process->readAllStandardError();
    });

    connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
          [=](int exitCode, QProcess::ExitStatus exitStatus)
    {
        qDebug() << "Process finished with exit code" << exitCode<<" "<<exitStatus;
    });
}

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

void MainWindow::on_btnOpen_clicked()
{
    // 设置要打开的文件路径
    QString filePath = "C:/Users/Lenovo/Desktop/1.txt";

    // 启动记事本并打开文件
    process->start("notepad", QStringList() << filePath);

    // 如果需要,可以等待记事本关闭
    //process->waitForFinished();
}

void MainWindow::on_btnClose_clicked()
{
    process->terminate();
}

关闭记事本程序后,会触发结束信号。

假如我们使用startDetached的方法打开记事本程序,因为它与父进程完全分离,不与父进程的QProcess实例进行通信,所以打开之后,我们无法再通过点击“关闭记事本”按钮关闭它,也无法接收到进程退出信号。如果关闭了父程序,记事本程序不会受到影响。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QProcess>
#include <QDebug>

// 创建 QProcess 对象
QProcess *process = nullptr;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    process = new QProcess(this);

    connect(process, &QProcess::readyReadStandardOutput, [&]() {
        qDebug() << "Standard output:" << process->readAllStandardOutput();
    });

    connect(process, &QProcess::readyReadStandardError, [&]() {
        qDebug() << "Standard error:" << process->readAllStandardError();
    });

    connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
          [=](int exitCode, QProcess::ExitStatus exitStatus)
    {
        qDebug() << "Process finished with exit code" << exitCode<<" "<<exitStatus;
    });
}

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

void MainWindow::on_btnOpen_clicked()
{
    // 设置要打开的文件路径
    QString filePath = "C:/Users/Lenovo/Desktop/1.txt";

    // 启动记事本并打开文件
    //process->start("notepad", QStringList() << filePath);

    process->startDetached("notepad", QStringList() << filePath);

    // 如果需要,可以等待记事本关闭
    //process->waitForFinished();
}

void MainWindow::on_btnClose_clicked()
{
    process->terminate();
}
示例2:执行不带管道的linux命令。
#include "widget.h"
#include "ui_widget.h"
#include <QProcess>
#include <QDebug>

// 创建 QProcess 对象
QProcess *process = nullptr;

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    process = new QProcess(this);

    connect(process, &QProcess::readyReadStandardOutput, [&]() {
        qDebug() << "Standard output:" << QString::fromUtf8(process->readAllStandardOutput());
    });

    connect(process, &QProcess::readyReadStandardError, [&]() {
        qDebug() << "Standard error:" << process->readAllStandardError();
    });

    connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
          [=](int exitCode, QProcess::ExitStatus exitStatus)
    {
        qDebug() << "Process finished with exit code" << exitCode<<" "<<exitStatus;
    });

    QStringList arguments;
    arguments << "-al" << "/home/zz";
    process->start("ls",arguments);

    process->waitForFinished();
}

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

运行结果: 

示例3:执行带有管道( | )的linux命令

process->start("bash", QStringList() << "-c" << "ps -ef | grep firefox");

QProcess不直接支持执行带有管道的命令,因为管道是shell的一个特性,而QProcess是直接执行程序而不是通过shell,可以尝试将整个管道命令作为单个字符串传递参数。

#include "widget.h"
#include "ui_widget.h"
#include <QProcess>
#include <QDebug>

// 创建 QProcess 对象
QProcess *process = nullptr;

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    process = new QProcess(this);

    connect(process, &QProcess::readyReadStandardOutput, [&]() {
        qDebug() << "Standard output:" << QString::fromLocal8Bit(process->readAllStandardOutput());
    });

    connect(process, &QProcess::readyReadStandardError, [&]() {
        qDebug() << "Standard error:" << QString::fromLocal8Bit(process->readAllStandardError());
    });

    connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
          [=](int exitCode, QProcess::ExitStatus exitStatus)
    {
        qDebug() << "Process finished with exit code" << exitCode<<" "<<exitStatus;
    });

    process->start("bash", QStringList() << "-c" << "ps -ef | grep firefox");

    process->waitForFinished();
}

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

运行结果:

示例4:执行带有重定向( >> )的命令。

process->start("bash", QStringList() << "-c" << "ping 127.0.0.1 >> ./test.txt");

重定向到本地test.txt路径下。

#include "widget.h"
#include "ui_widget.h"
#include <QProcess>
#include <QDebug>

// 创建 QProcess 对象
QProcess *process = nullptr;

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    process = new QProcess(this);

    connect(process, &QProcess::readyReadStandardOutput, [&]() {
        qDebug() << "Standard output:" << QString::fromLocal8Bit(process->readAllStandardOutput());
    });

    connect(process, &QProcess::readyReadStandardError, [&]() {
        qDebug() << "Standard error:" << QString::fromLocal8Bit(process->readAllStandardError());
    });

    connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
          [=](int exitCode, QProcess::ExitStatus exitStatus)
    {
        qDebug() << "Process finished with exit code" << exitCode<<" "<<exitStatus;
    });

    process->start("bash", QStringList() << "-c" << "ping 127.0.0.1 >> ./test.txt");

    process->waitForFinished();
}

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

运行结果:

示例5:传递子程序main函数参数。

假如两个程序都是自己开发的,父进程需要传递给子进程main函数参数,很简单

process->start("./parent.exe p1 p2 p3");

6.更多参考

Qt+FFmpeg+opengl从零制作视频播放器-1.项目介绍_qt opengl视频播放器-CSDN博客

libVLC 提取视频帧使用OpenGL渲染-CSDN博客

QT UDP通信(单播、广播、组播)-CSDN博客

QCharts -1.概述-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/543444.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode 394. 字符串解码

心路历程&#xff1a; 这道题看到括号直接想到栈&#xff0c;五分钟新题直接秒了&#xff0c;一开始以为需要两个栈分别存储数字和非数字&#xff0c;后来发现一个栈就够了&#xff0c;思路如图&#xff1a; 这道题考察的应该是队栈这两种数据结构的转换&#xff0c;因为每次…

LangChain - 文档加载

文章目录 一、关于 检索二、文档加载器入门指南 三、CSV1、使用每个文档一行的 CSV 数据加载 CSVLoader2、自定义 csv 解析和加载 &#xff08;csv_args3、指定用于 标识文档来源的 列&#xff08;source_column 四、文件目录 file_directory1、加载文件目录数据&#xff08;Di…

缺少vcruntime140_1.dll

windows安装mysql的时候错误提示&#xff1a; 64位下载安装&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1u_ALo0JMc-Y2an22l1Y1EA 提取码&#xff1a;ve10 32位下载安装&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/16XTt642Tj-Oc-WvbgQK-Ww 提取码…

学校4-11天梯赛选拔赛

目录 L1-5 6翻了 题目 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 思路 AC代码 L1-1 嫑废话上代码 题目 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; AC代码 L1-8 刮刮彩…

MySQL_00001_00000

数据准备 员工表&#xff1a;emp Oracle: create table emp ( empno number(4) not null, ename varchar2(10), job varchar2(9), mgr number(4), hiredate date, sal number(7, 2), comm number(7, 2), deptno number(2) ); insert into em…

bugku-web-decrypt

这里的提示解密后没有什么意义 这里下载文件包 得到一个index.php文件 得到代码 <?php function encrypt($data,$key) {$key md5(ISCC);$x 0;$len strlen($data);$klen strlen($key);for ($i0; $i < $len; $i) { if ($x $klen){$x 0;}$char . $key[$x];$x1;}for…

计算机炸了,电子信息也是劝退专业?

还不是因为这个版本&#xff0c;计算机专业受到了制裁&#xff0c;导致这些偏计算机类的专业也受到了牵连 我本科的时候是一所双一流院校的计科专业&#xff0c;我们学校的电子信息专业堪称苦逼&#xff0c;我们计科学的东西&#xff0c;他们都要学&#xff0c;他们学的一些东…

什么是享元模式,有哪些具体应用

一、定义 享元模式是一种通过尽可能多地共享数据来最小化内存使用和对象数量&#xff0c;从而提高性能的设计模式。在享元模式中&#xff0c;如果需要相同数据的多个对象&#xff0c;则共享这些对象而不是创建新的对象&#xff0c;从而提高系统的效率。 其实有很多应用场景&am…

基于顺序表实现通讯录

上篇我们讲了顺序表是什么&#xff0c;和如何实现顺序表。这篇文章我们将基于顺序表来实现通讯录。 文章目录 前言一、基于顺序表是如何实现的二、通讯录的头文件和实现文件三、通讯录的实现3.1 定义通讯录结构3.2 初始化通讯录3.3 销毁通讯录3.4 通讯录添加数据3.5 查找联系人…

golang 使用栈模拟计算器

思路&#xff1a; // Author sunwenbo // 2024/4/12 16:51 package mainimport ("errors""fmt""strconv" )// 使用数组来模拟一个栈的应用 type Stack struct {MaxTop int //表示栈最大可以存放数的个数Top int //表示栈底&#xff…

【QT入门】Qt自定义控件与样式设计之自定义QLineEdit实现搜索编辑框

往期回顾 【QT入门】Qt自定义控件与样式设计之qss的加载方式-CSDN博客 【QT入门】Qt自定义控件与样式设计之控件提升与自定义控件-CSDN博客 【QT入门】Qt自定义控件与样式设计之鼠标相对、绝对位置、窗口位置、控件位置-CSDN博客 【QT入门】Qt自定义控件与样式设计之自定义QLin…

蓝桥杯之注意事项

1.特殊求解的地方 2.一些数学公式 比如二叉树求全深度数值那道题 3.掌握有关库函数 #include<algorithm> 包含sort&#xff08;&#xff09;函数【排列函数】C sort()排序详解-CSDN博客&#xff0c;next_permutation()函数【求解全排列问题】求解数组大小sizeof(arr…

2024年腾讯云最新优惠活动及领券入口整理分享

随着云计算技术的快速发展&#xff0c;越来越多的企业和个人选择将业务部署在云端。腾讯云作为国内知名的云计算服务提供商&#xff0c;为用户提供了丰富的云产品和服务。为了帮助用户降低成本&#xff0c;腾讯云定期推出各种优惠活动。本文将为大家整理分享2024年腾讯云的最新…

亲测能用MathType7破解版本安装包百度网盘下载

MathType 7是一款专业的数学公式编辑工具&#xff0c;广泛应用于教育教学、科研机构、工程学、物理学、化学等多个领域。它支持各种数学符号、公式、方程式、矩阵、分数、上下标等&#xff0c;几乎涵盖了所有的数学元素&#xff0c;可以帮助用户快速、方便地创建高质量的数学公…

【Cesium学习笔记】二、隐藏控件及按钮

【Cesium学习笔记】二、隐藏控件及按钮 一、隐藏控件二、隐藏cesium图标 Ps:本教程所有代码于同一个工程中&#xff0c;运行npm run dev默认首页为App.vue&#xff0c;只需替换App.vue的内容即可切换不同页面。 将上一节的App.vue保存为类似“加载cesium.vue”这种对应名称。 …

如何在Photoshop中,使用本地Stable Diffusion WebUI的绘图能力

&#x1f3c3;‍♂️文章背景 相信设计师朋友们最熟悉的软件应该就是photoshop了&#xff0c;现在AI绘图虽然控制性越来越强&#xff0c;但跟ps比起来&#xff0c;还是要弱很多&#xff0c;尤其是图层、蒙版、笔刷、色调校色等等功能&#xff0c;所以就算是使用SD或者midjourn…

虚拟机下CentOS7开启SSH连接

虚拟机下CentOS7开启SSH连接 自己在VMware中装了CentOS 6.3&#xff0c;然后主机&#xff08;或者说xshell&#xff09;与里面的虚拟机连不通&#xff0c;刚学习&#xff0c;一头雾水&#xff0c;查了半天&#xff0c;也不知道怎么弄。 在虚拟机&#xff08;Vmware Workstatio…

2024蓝桥A组A题

艺术与篮球&#xff08;蓝桥&#xff09; 问题描述格式输入格式输出评测用例规模与约定解析参考程序难度等级 问题描述 格式输入 无 格式输出 一个整数 评测用例规模与约定 无 解析 模拟就好从20000101-20240413每一天计算笔画数是否大于50然后天数&#xff1b; 记得判断平…

Linux 网络排查命令

端口相关服务检查 netstat -ntpl|grep [$Port]说明&#xff1a;[$Port]为相应的端口号。 0.0.0.0代表本机上可用的任意地址。比如&#xff0c;0.0.0.0:80表示本机上所有地址的80端口。 tcp 0.0.0.0:80表示在所有的可用接口上监听TCP的80端口 如果返回结果为空&#xff0c;说明…

rocketmq和rabbitmq总是分不清?

1. 官方解答 摘自百度搜索&#xff1a; 2. 通俗易懂的回答