- 注意事项
假设有程序A、程序B和数据库D。B使用了数据库D(调用时使用了相对路径)且与D在同一目录下。
直接运行B时,能够正确访问数据库D,而当由A调用B时,B启动后却无法正常访问数据库D。出现这个问题的原因是被A调用的B相当于在A的目录下执行,即在A的同一目录下,B无法找到D。
要避免出现上述的问题有以下3个方法:
1. 在B中对数据库的访问使用绝对路径
2. 把A、B两个程序的执行目录合并(对于上述例子来说就是把A、B、D三个文件置于同一目录)
3. 把数据库D拷贝到A的同一目录下
推荐采用方法2,合并后的目录可作为一个整体,移动到任意目录下都能正常运行,同时也便于管理。
1. 在B中对数据库的访问使用绝对路径
2. 把A、B两个程序的执行目录合并(对于上述例子来说就是把A、B、D三个文件置于同一目录)
3. 把数据库D拷贝到A的同一目录下
推荐采用方法2,合并后的目录可作为一个整体,移动到任意目录下都能正常运行,同时也便于管理。
- 头文件
- C缓冲机制
若希望获取QProcess调用的外部程序的标准输出,则须了解C语言的缓冲机制。
外部程序中的输出方法:
printf("...");
fprintf(stdout, "Hello STDOUT!\n");
fprintf(stderr, "Hello STDERR!\n");
缓冲方式:行缓冲、全缓冲
刷新缓冲区:
fflush(stdout);
fflush(stdin);
fflush(stderr);
- 基本操作
// 获取外部程序标准输出
connect(&mProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(redFromStdOut()));
...
void FloodForecast::redFromStdOut()
{
ui.textBrowse->append(mProcess.readAllStandardOutput());
}
// 获取外部程序标准错误
connect(&mProcess, SIGNAL(readyReadStandardError()), this, SLOT(redFromStdErr()));
...
void FloodForecast::redFromStdErr()
{
ui.textBrowse->append(mProcess.readAllStandardError());
}
// 外部程序启动失败
connect(&mProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
...
void FloodForecast::processError(QProcess::ProcessError error)
{
if(error==QProcess::FailedToStart)
{
ui.textBrowse->append("<font color=red>程序启动失败.</font>\r\n");
}
}
// 外部程序结束
connect(&mProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
...
void FloodForecast::processFinished(int exitCode,QProcess::ExitStatus exitStatus)
{
if(exitStatus == QProcess::CrashExit)
{
ui.textBrowse->append("<font color=red>程序异常终止.</font>\r\n");
}
else
{
ui.textBrowse->append("<font color=green>程序正常结束.</font>\r\n");
}
}
- 调用方式
- 非阻塞方式
QProcess::startDetached("/opt/led 0 0");
调用的结果相当于在Shell中执行“/opt/led 0 0”,startDetached()方法不等led执行完,马上返回。该方法可用来调出系统终端(终端也是一个程序)。
- 阻塞方式
process->start("...");
外部程序启动后会阻塞原来的程序,直到外部程序退出,可结合线程解决此问题。这种方式的调用下,当原来的程序退出时,外部程序不受影响。
- 简单示例
#include <QProcess>
QProcess *cmdPing;
cmdPing = new QProcess(this);
connect(cmdPing, SIGNAL(readyRead()), this, SLOT(slot_Network_ReadCmdOutput()));
connect(cmdPing, SIGNAL(finished(int)), this, SLOT(slot_Network_CmdFinished(int)));
cmdPing->start("ping 192.168.0.124 -c 5");
void MainWindow::slot_Network_ReadCmdOutput()
{
ui->tb_Network_Msg->insertPlainText(cmdPing->readAll());
ui->tb_Network_Msg->verticalScrollBar()->setSliderPosition(
ui->tb_Network_Msg->verticalScrollBar()->maximum());
}
void MainWindow::slot_Network_CmdFinished(int ret)
{
// 当ping通时,ret = 0;当无法ping通时,ret != 0
...
ui->pb_Network_Ping->setEnabled(true);
ui->pb_Network_Udp->setEnabled(true);
}