qt - 如何在 C++ 代码中的一些“繁重”操作之前使 QML 对象可见
问题描述
我在 QML 中有以下逻辑:
button click handler in QML:
1) rectangle.visible=true
2) call some C++ method
在 C++ 方法中,我调用 QFile::copy,它从 USB 存储复制文件,并将日志打印到上面的矩形(必须已经可见)。但据我了解,QML 仅在执行按钮单击处理程序后才使元素可见,但 QFile::copy 太慢,所以我只有在复制所有文件后才能看到日志(矩形变为可见)。所以我的问题是,如何在调用 QFile::copy 之前使包含日志的矩形可见(真正“可见”)。当然我可以实现异步复制,但我是 Qt 的新手,所以可能有一些解决方案。
谢谢
解决方案
把你的大任务放在一个QThread
:
任务.hpp
#ifndef THETASK_HPP
#define THETASK_HPP
#include <QThread>
class TheTask: public QThread
{
Q_OBJECT
public:
TheTask(/* Put operation args here, or through some setters. */);
protected:
void run() override;
// Put stuff for storing operation's arguments and results here.
};
#endif // THETASK_HPP
任务.cpp
#include "thetask.hpp"
TheTask::TheTask() :
QThread()
// Init stuff for storing operation's arguments and results.
{}
void TheTask::run() {
// Put your heavy C++ operation here
}
重的.hpp
#ifndef HEAVY_HPP
#define HEAVY_HPP
#include <QObject>
#include <QList>
class TheTask;
class Heavy: public QObject
{
Q_OBJECT
public:
Heavy();
virtual ~Heavy();
/// @brief QML registration
static void declareQML();
/// @brief Your heavy operation
Q_INVOKABLE void doTheBigOperation(/* Operation args */);
protected:
/// @brief Storing the running threads for objects lifecycle reasons.
///
/// The bigOp object would be destroyed at the end of the
/// Heavy::doTheBigOperation() method. In order to keep it alive,
/// let's store it in a list.
QList<TheTask *> bigOps;
signals:
/// @brief Emitted when everything is finished.
void afterBigOp(/* Put operation results here */);
protected slots:
/// @brief Treatments to do when the operation is finished.
void bigOpFinished();
};
#endif // HEAVY_HPP
重的.cpp
#include "anchor.hpp"
#include <QQmlEngine>
#include "thetask.hpp"
Heavy::Heavy() :
QObject(),
bigOps()
{}
Heavy::~Heavy() {
// Delete threads pointers properly.
while (!bigOps.isEmpty()) {
TheTask * thread = bigOps.takeLast();
// Stopping threads. Be careful on consequences.
thread->quit();
thread->wait();
thread->deleteLater();
}
}
void Heavy::declareQML() {
qmlRegisterType<Heavy>("CppGates", 13, 37, "Heavy");
}
void Heavy::doTheBigOperation(/* Operation args */) {
TheTask * bigOp = new TheTask(/* Operation args */);
// A thread emits the QThread::finised() signal when its task is finished.
connect(bigOp, &TheTask::finished,
this, &Heavy::bigOpFinished);
// Keeping the thread alive (cf. bigOps documentation).
bigOps << bigOp;
// Start executing the heavy operation.
bigOp->start();
}
void Heavy::bigOpFinished() {
// Retrieving the thread, which is the signal sender.
TheTask * thread = qobject_cast<TheTask *>(sender());
// The treatment is over: let's broke communication with its thread.
disconnect(thread, &TheTask::finished,
this, &Heavy::bigOpFinished);
// Extract operation results from the thread.
// Removing the thread from the running threads list.
int threadIndex = bigOps.indexOf(thread);
bigOps.removeAt(threadIndex);
thread->deleteLater();
// Telling QML that the heavy operation is over.
emit afterBigOp(/* Operation results */);
}
RectComp.qml
import QtQuick 2.12
import CppGates 13.37
Item {
id: qml_comp
Heavy { id: controller }
Rectangle {
id: rectangle
// ...
}
function doItHeavy() {
rectangle.visible = false
controller.doTheBigOperation(/* Operation arguments */)
}
function afterTheBigOp(/* Operation results */) {
// Put here things you would like to do after controller.doTheBigOperation()
}
Component.onCompleted: {
// Connecting a callback to the signal emitted after the heavy operation.
controller.afterBigOp.connect(qml_comp.afterTheBigOp)
}
}
主文件
#include <QApplication>
#include <QQmlApplicationEngine>
#include "heavy.hpp"
int main(int argc, char ** argv() {
QApplication app(argc, argv);
// ...
Heavy::declareQML();
// ...
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
int res = engine.rootObjects().isEmpty() ? -1 : app.exec();
// ...
return res;
}
有关更多信息,请查看QThread
参考:https ://doc.qt.io/qt-5/qthread.html
推荐阅读
- python - 如何确定 GridSearchCV 中每个评分指标的最佳参数和最佳分数
- android - 在对话框之前显示 admob 的正确方法
- typescript - 根据方法中的其他参数推断参数类型
- python - 有什么方法可以加速 pyspark 中的缓存过程?
- javascript - Angular 6中的嵌套三元条件
- python - 安全地存储 REST API 凭据以在 Python 环境中访问
- perl - 如何保存您在 perl 中搜索的模式
- json - Spring 从 PostgreSQL 转换为 Geojson FeatureCollection
- apache-spark - 如何将命名参数发送到 spark-submit
- azure-machine-learning-service - AzureML:自动缩放 ML 端点