如何从QT Creator 4.2.0中创建的QT GUI应用程序启动和终止python脚本



我在QT Creator 4.2.0中创建了一个简单的应用程序,即QT小工具应用程序,使用了所有默认值。增加了一个按钮。我试着模仿我在网上找到的多个帖子,但无法正确启动python脚本。我一直收到这样的消息:

QProcess:在进程("python.exe")仍在运行时销毁。

Python.exe添加到Path变量中。

我希望的是,当按下按钮时,启动python脚本,然后等待一段时间(但不要锁定GUI),然后终止python脚本。

很抱歉,我是c++/QT的新手。

我的QT代码如下:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QProcess>
#include <QDir>
#include <QCoreApplication>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
//define file paths..  make sure the paths work
QDir dir1("C:/SFI/FastScan/Calibration/");
QFile file1("C:/SFI/FastScan/Calibration/pytest.py");
QString script1 = "C:/SFI/FastScan/Calibration/pytest.py";
QFile file2(script1);
qDebug() << dir1.exists() << file1.exists() << file2.exists();
//  these all result in true, true true
// latest method I tried
QString command("python.exe");
QStringList args;
args << script1;
QProcess *myProcess = new QProcess(this);
myProcess->start(command,args);
}

下面是python脚本,python 2.7。。。

#!/usr/bin/env python
import time
while True:
time.sleep(1)
print time.time()

编辑:我坚持了下来,通过用这两行代码替换QT代码的最后5行,我可以启动我的python脚本

QProcess *myProcess = new QProcess();
myProcess->startDetached("python.exe C:/SFI/FastScan/Calibration/pytest.py" );

我尝试过使用myProcess.terminate(),但无法让脚本退出。

当您在QProcess上调用start时,它会运行脚本,但不会等待脚本完成,因此问题中的on_pushButton_clicked()函数将在启动后退出,并且无法终止脚本。

startDetached是一个静态函数,它独立于调用进程运行进程,因此没有办法杀死它,因为myProcess对象没有保留已启动进程的句柄。对于您的应用程序,调用start是更好的方法。

这样做的一种方法是:

myProcess->start(command, args);
//check that the process actually starts
if (!myProcess->waitForStarted()) {
qDebug("Could not start process");
return;
}

QTime time;
time.start();
//wait 4 seconds
while (time.elapsed() < 4000) {
//keep the GUI working
QApplication::processEvents();
}
myProcess->kill();
// wait for the process to actually stop
myProcess->waitForFinished();
delete myProcess;

启动后,循环等待4秒钟,然后终止进程。processEvents函数在等待时保持GUI的活动状态。

在调用kill之后,您需要调用waitForFinished来等待进程实际完成,否则您会在进程实际终止之前看到QProcess对象被销毁的错误。

上述方法的问题是GUI在on_pushButton_clicked()函数中继续工作。因此,如果您在循环中从GUI调用了一个"退出"函数,那么应用程序将在脚本仍在运行的情况下退出。因此,如果您只想在GUI中更新进度条或其他显示小部件,那么这种方法就是OK。在这种情况下,您可以将QEventLoop::ExcludeUserInputEvents传递给processEvents

如果用户可以在GUI中做其他事情,那么我会将QProcess作为类成员,并创建一个单独的槽来终止脚本。然后,您可以使用QTimer在指定的时间间隔后调用此插槽。

最新更新