如何在后台运行SequentialAnimation?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在后台运行SequentialAnimation?相关的知识,希望对你有一定的参考价值。

我正在设计Qt5.7 / QML应用程序。主要思想是按下按钮会触发shell命令,这需要很长时间。此命令的结果应反映在窗口小部件中。 与此同时,我需要运行SequentialAnimation,以向用户显示后台正在发生的事情。所以我启动动画,然后调用发送shell命令的进程。 但是动画似乎被冻结为整个GUI,直到shell命令返回。 有什么建议? QML代码:

    CircularGauge {
        id: speedometer_wr
        x: 199
        y: 158
        value: valueSource.bps
        maximumValue: 400
        width: height
        height: container.height * 0.5
        stepSize: 0
        anchors {
            verticalCenter: parent.verticalCenter
            verticalCenterOffset: 46
        }
        style: DashboardGaugeStyle {}

        NumberAnimation {
            id: animation_wr
            running: false
            target: speedometer_wr
            property: "value"
            easing.type: Easing.InOutSine
            from: 0
            to: 300
            duration: 15000
        }
    }

    Button {
        id: button_benchmark
        x: 168
        y: 26
        width: 114
        height: 47
        text: qsTr("Benchmark")
        tooltip: "Execute the performance test"
        checkable: true
        function handle_becnhmark() {
            speedometer_wr.value = 0;

            // Uncheck the button
            button_benchmark.checked = false;

            // Start the animation
            animation_wr.start();

            // Run the benchmark
            var res = backend.run_benchmark();

            // Stop the animation
            animation_wr.stop();

            speedometer_wr.value = parseFloat(res.split(",")[0]);
        }
        onClicked: {handle_becnhmark()}
    }

Cpp代码:

#include <QProcess>
#include <QtDebug>
#include "backend.h"
#include <QRegExp>

BackEnd::BackEnd(QObject *parent) : QObject(parent)
{

}

QString BackEnd::run_benchmark() {
    qDebug() << "in run_benchmark";
    QProcess proc;

    // Execute shell command
    proc.start(<LONG_SHELL_COMMAND>);
    if (!proc.waitForStarted())
        return "";
    if (!proc.waitForFinished())
        return "";

    // Get the results, parse and return values
     QString result(proc.readAll());
    return result;
}
答案

这是单线程应用程序的问题。您需要在另一个线程中运行shell命令的执行。只要看看QThread使用的例子。主要的是你需要在GUI和后端之间进行基于信号槽的通信(如果你在后端调用一些“硬”功能)。

使用线程可以在许多方面实现,例如使用硬盘驱动器(读取/写入文件),对服务器或数据库的请求。所有这一切都可以同步或asynchrony。你的基本意义 - 它是否会冻结主要过程(答案 - 异步方法不会)。

在您的应用程序中使用QProcess调用一些外部命令。 QProcess start()方法将自动异步执行此命令。这意味着您不需要使用QThreads。但是,如果你使用waitForFinished()它会发生。如果您将阅读QProcess reference,您会看到waitForStarted()waitForFinished()方法是同步的。这意味着他们确实会冻结主进程和GUI。

所以你需要的是

  • 在类头中声明指向QProcess的指针(最好使用QSharedPointer<QProcess>class BackEnd : public QObject { ... private slots: void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus); signals: void executionEnds(const QString &res); private: QProcess* proc; }
  • 在源代码中,您需要初始化proc并将QProcess finished()信号连接到插槽,该插槽将proc命令执行的输出推送到BackEnd中的另一个信号。 BackEnd::BackEnd(QObject *parent) : QObject(parent) { proc = new QProcess(); connect(proc, &QProcess::finish, this, &BackEnd::handleProcFinished); } void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus) { //check code ... QString result(""); if (all is fine) { result = proc->readAll(); } else { //debug or something else } emit executionEnds(result); }

在QML方面,它将是这样的:

Button {
    onClicked: {
        speedometer_wr.value = 0;
        // Uncheck the button
        button_benchmark.checked = false;
        // Start the animation
        animation_wr.start();
        // Run the benchmark
        var res = backend.run_benchmark();
    }
}
Connections {
    target: backend //[name of some contextProperty which will be emiting the signals]
    onExecutionEnds: {
        animation_wr.stop();
        if (res != "") {
            speedometer_wr.value = parseFloat(res.split(",")[0]);
        }
    {
}

以上是关于如何在后台运行SequentialAnimation?的主要内容,如果未能解决你的问题,请参考以下文章

如何保持活动在后台运行? [复制]

linux 如何后台运行

如何实现unity在后台运行

如何在 iOS 10 的后台运行 xmpp?

如何查看电脑后台正在运行的程序

如何在后台运行Linux命令?