Qt扫盲-QProcess理论总结

一、概述

QProcess 其实更多的是与外面进程进行交互的一个工具类,通过这个类来启动外部进程,获取这个进程的标准输出,同时也可以向这个类写入数据,外部进程根据写入的指令执行对应的命令,我们可以也可能获取到输出,但是这种输出是取决于外部的进程。

二、使用

要启动一个进程外部,需要将要运行的程序的名称和命令行参数作为参数传递给start()。就很像命令行里面的执行一样。

多参数可以存放在 QStringList 数组中。

或者,你可以设置这个程序,让它使用setProgram()和setArguments()运行,然后调用start()或open()。

例如,下面的代码片段在X11平台上以 Fusion 样式运行模拟时钟示例,其参数列表中包含" style"和" Fusion "两项:

QObject *parent;
      ...
QString program = "./path/to/Qt/examples/widgets/analogclock";
QStringList arguments;
arguments << "-style" << "fusion";
QProcess *myProcess = new QProcess(parent);
myProcess->start(program, arguments);

然后,QProcess进入启动状态,当外部进程开始时,QProcess进入运行状态,并发出 started() 信号。

QProcess 允许我们将进程视为 序列I/O 设备。因为 QProcess 本身继承至 QIODevice 类,我们可以对进程进行读写,就像使用QTcpSocket 访问网络连接一样。然后,你可以调用write()来写入进程的标准输入,并调用read()、readLine() 和 getChar() 来读取标准输出。因为它继承了QIODevice,所以QProcess 也可以用作 QXmlReader 的输入源,或者用来生成要使用QNetworkAccessManager上传的数据。

当外部进程退出时,QProcess 重新进入NotRunning 状态(初始状态),并发出 finished() 信号。
finished()信号提供了进程的退出代码和退出状态作为参数,你还可以调用exitCode()来获得最后一个已经完成的进程的退出代码,调用exitStatus()来获得它的退出状态。

如果在任何时间点发生错误,QProcess将发出erroroccurs()信号。你还可以调用error()来查找上次发生的错误类型,调用state()来查找当前进程的状态。

  • 注意:VxWorks、iOS、tvOS、watchOS或UWP平台不支持QProcess。

三、通过 Channel 通道通信

进程有两个预定义的输出通道:

  • 标准输出通道(stdout)提供常规控制台输出
  • 标准错误通道(stderr)通常提供进程打印的错误。

这些通道代表两个独立的数据流。你可以通过调用setReadChannel()来切换它们。

当数据在当前读通道上可用时,QProcess发出 readyRead() 【这个是继承至 QIODevice 的功能】。

当有新的标准输出数据时,它还会触发readyReadStandardOutput()
当有新的标准错误数据时,它还会触发readyreadstandardror()。

除了调用read()、readLine()或getChar(),你还可以通过调用 readAllStandardOutput() 或 readallstandderror() 显式地从两个通道中读取所有数据。

这些频道的术语可能会引起误解。
请注意,进程的输出通道对应于QProcess的读通道,而进程的输入通道对应于QProcess的写通道。这是因为我们使用QProcess 读取的内容是过程的输出,而我们写入的内容成为过程的输入。我们读的就是外部进程的输出,我们写的就是外部进程的输入。

QProcess 可以合并两个输出通道,使来自运行过程的标准输出和标准错误数据都使用标准输出通道。在启动进程之前,使用MergedChannels 调用setProcessChannelMode( )来激活此功能。

您还可以选择将ForwardedChannels作为参数,将正在运行的进程的输出转发给调用的主进程。也可以只转发一个输出通道——通常会使用ForwardedErrorChannel,但也存在ForwardedOutputChannel。请注意,在GUI应用程序中使用通道转发通常是一个坏主意——您应该以图形方式显示错误。

某些进程需要特殊的环境设置才能运行。调用setProcessEnvironment()可以设置进程的环境变量。
要设置工作目录,可以调用setWorkingDirectory()。默认情况下,进程运行在调用进程的当前工作目录中。

以QProcess启动的GUI应用程序的窗口位置和层叠顺序由底层窗口系统控制。对于Qt 5应用程序,可以使用
-qwindowgeometry 命令行选项指定位置;X11应用程序通常接受-geometry命令行选项。

注意:在QNX上,由于操作系统的限制,设置工作目录可能会导致除QProcess调用者线程之外的所有应用程序线程在生成过程中暂时冻结。

四、同步进程API

在第三里面提到的一些信号槽都是异步处理,不会说会存在同步的问题,下面的就是一些同步阻塞的一些API,大部分都是继承了 QIODevice 的功能。

QProcess提供了一组函数,通过暂停调用线程直到发出某些信号,允许它在没有事件循环的情况下使用:

  • waitForStarted()会阻塞进程直到进程开始
  • waitForReadyRead()将阻塞到当前读通道有新数据可读为止。
  • waitForBytesWritten()将阻塞,直到有一个有效的数据写入进程。
  • waitForFinished()会阻塞,直到进程结束。

从主线程(调用QApplication::exec()的线程) 调用这些函数可能会导致用户界面冻结。 一般来说很大可能必然卡界面

下面的例子运行gzip来压缩字符串"Qt rocks!",没有使用事件循环,也就是信号槽的功能

      QProcess gzip;
      gzip.start("gzip", QStringList() << "-c");
      if (!gzip.waitForStarted())
          return false;

      gzip.write("Qt rocks!");
      gzip.closeWriteChannel();

      if (!gzip.waitForFinished())
          return false;

      QByteArray result = gzip.readAll();

五、注意事项

1. 平台特性

有些Windows命令(例如dir)不是由单独的应用程序提供的,而是由命令解释器本身提供的。如果试图使用QProcess直接执行这些命令,它将不起作用。

一种可能的解决方案是执行命令解释器本身(在某些Windows系统上是cmd.exe),并要求解释器执行所需的命令。

就需要用 这种,有时候需要加上 ‘\n’ 表示回车

QProcess cmdProcess;
cmdProcess.start("cmd");

cmdProcess.write("dir\n");

2. 不能实时读取

很大可能就是 外部进程不是马上输出的,需要把标准的输出给 刷新下去,比如在外部执行一个 py 脚本

for i in range(1,1000):
	if i % 2:
		for y in range(1,800000):
			if y == 999:				
				print("num i = {0}".format(i))

上面我实验的时候本来期望一次一次输出,在QProcess 里也能一次一次获取,但是不行,上面那个会输出完才一起输出

下面这个就可以一次一次获取输出。不设置缓存,全部输出出去。

import sys

for i in range(1,1000):
	if i % 2:
		for y in range(1,800000):
			if y == 999:				
				sys.stdout.write("num i = {0}".format(i))
				sys.stdout.flush()
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
QtQProcess类是一个用于启动和控制外部程序的类。通过使用QProcess,可以在Qt应用程序启动其他应用程序,并与其进行交互。 要使用QProcess启动外部程序,可以选择一体式和分离式两种方式。一体式方式使用start函数,需要传递外部程序的路径和执行参数。例如,使用setProgram函数设置外部程序的路径,使用setArguments函数设置执行参数,然后使用start函数启动程序。例如: ``` QString program = "./path/to/program"; QStringList arguments; arguments << "arg1" << "arg2"; QProcess *myProcess = new QProcess(); myProcess->setProgram(program); myProcess->setArguments(arguments); myProcess->start(); ``` 分离式方式使用startDetached函数,可以在后台启动外部程序。这种方式不会等待外部程序执行完成,适用于不需要与外部程序进行交互的情况。 使用QProcess还可以通过设置管道来与外部程序进行交互,例如通过读取外部程序的输出或向其发送输入。 总之,QtQProcess类提供了方便的接口来启动和控制外部程序,使得Qt应用程序可以与其他应用程序进行集成和交互。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Qt 5.12--QProcess](https://blog.csdn.net/qq_38880380/article/details/107456432)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

太阳风暴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值