简体   繁体   English

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

[英]How to launch and terminate a python script from a QT GUI app created in QT Creator 4.2.0

I've created a simple app in QT Creator 4.2.0, ie, QT Widgets Application, used all defaults. 我在QT Creator 4.2.0中创建了一个简单的应用程序,即QT Widgets Application,使用了所有默认设置。 Added one button. 添加了一个按钮。 I've tried to mimic multiple posts I've found around web, but can not get a python script to launch correctly. 我试图模仿在网上找到的多个帖子,但是无法正确启动python脚本。 I keep getting this message: 我不断收到此消息:

QProcess: Destroyed while process ("python.exe") is still running. QProcess:进程(“ python.exe”)仍在运行时被破坏。

Python.exe is added to Path variable. 将Python.exe添加到Path变量。

What I would like to happen is, when the button is pressed, launch the python script, and then wait some amount of time (but don't lock up the GUI), then terminate python script. 我想发生的是,当按下按钮时,启动python脚本,然后等待一段时间(但不要锁定GUI),然后终止python脚本。

I apologize, I'm very new to c++/QT. 抱歉,我对c ++ / QT还是很陌生。

My QT code is below: 我的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);

}

The python script is below, python 2.7 ... python脚本如下,python 2.7 ...

#!/usr/bin/env python

import time

while True:
    time.sleep(1)
    print time.time()

Edit: I kept at it, by replacing the last 5 lines of my QT code with these two lines I can launch my python script, 编辑:我一直坚持下去,通过用这两行替换我的QT代码的最后5行,我可以启动python脚本,

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

I've tried to use the myProcess.terminate() , but can not get the script to exit. 我尝试使用myProcess.terminate() ,但是无法退出脚本。

When you call start on QProcess it runs the script but does not wait for it to finish so your on_pushButton_clicked() function as it is in the question will exit after starting and there will be no way to kill the script. 当您在QProcess上调用start时,它将运行脚本,但不等待其完成,因此问题中的on_pushButton_clicked()函数将在启动后退出,并且将无法on_pushButton_clicked()该脚本。

startDetached is a static function that runs the process independently of the calling process so there is no way to kill it as the myProcess object does not keep a handle to the started process. startDetached是一个静态函数,可独立于调用进程运行进程,因此无法杀死它,因为myProcess对象不会保留已启动进程的句柄。 For your application calling start is the better approach. 对于您的应用程序,调用开始是更好的方法。

One way to do this would be like this: 一种方法是这样的:

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;

After starting, the loop waits for 4 seconds before killing the process. 启动后,循环等待4秒钟,然后终止进程。 The processEvents function keeps the GUI alive while waiting. processEvents函数可在等待时使GUI保持活动状态。

After calling kill, you need to call waitForFinished to wait for the process to actually finish otherwise you get the error you saw as the QProcess object is destroyed before the process has actually terminated. 调用kill之后,您需要调用waitForFinished来等待进程实际完成,否则您将看到在进程实际终止之前销毁QProcess对象时看到的错误。

The problem with the above approach is that the GUI continues to function, while in the on_pushButton_clicked() function. 上述方法的问题在于,GUI在on_pushButton_clicked()函数中继续运行。 So if you called an "exit" function from the GUI while in the loop the application would exit with the script still running. 因此,如果您在循环中从GUI调用“退出”功能,则应用程序将退出,并且脚本仍在运行。 So this approach is OK if all you want to do in the GUI is update a progress bar or other display widget. 因此,如果您要在GUI中做的只是更新进度条或其他显示小部件,则此方法是OK In that case you could pass QEventLoop::ExcludeUserInputEvents to processEvents . 在这种情况下,您可以将QEventLoop::ExcludeUserInputEvents传递给processEvents

If the user can do other things in the GUI then I would make the QProcess a class member and create a separate slot to kill the script. 如果用户可以在GUI中做其他事情,那么我将使QProcess成为类成员,并创建一个单独的插槽来杀死脚本。 You could then use a QTimer to call this slot after a specified time interval. 然后,您可以在指定的时间间隔后使用QTimer调用此插槽。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM