關于這個主題有幾個問題與我的問題無關,他們沒有為我產生任何結果。
想象一下,我在 QML 中有一個帶有AnimatedImage的啟影片面,當我的重型組件在后臺加載時我想顯示它,所以我使用加載器在后臺加載資產,但是當加載器開始加載我的 UI 時凍結(即 AnimatedImage) ,我可以看到 BusyIndi??cator 沒有凍結。
我在github 存盤庫中提供了完整的源代碼,以便您可以更輕松地對其進行測驗。
我的問題是:
- Loader 真的在后臺運行嗎(例如,如果我試圖在建構式中連接到服務器,Loader 可以處理這種情況還是我必須在另一個執行緒中運行它)?
- 應如何處理此類情況,以免我看到任何故障?
視窗.qml
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts
Window {
id:mainWindow
y:100
width: 640
height: 480
visible: true
flags: Qt.FramelessWindowHint
//splash screen
Popup {
id: popup
width: mainWindow.width
height: mainWindow.height
modal: false
visible: true
Overlay.modeless: Rectangle {
color: "#00000000"
}
//Splash loader
Loader{
id: splash
anchors.fill: parent
source: "qrc:/Splashscreen.qml"
}
}
// Timer that will start the loading heavyObjects
Timer {
id: timer
interval: 2000
repeat: false
running: true
onTriggered: {
loader.source = "qrc:/heavyObjects.qml"
loader.active = true
}
}
//write a loader to load main.qml
Loader {
id: loader
anchors.fill: parent
asynchronous: true
active: false
//when loader is ready, hide the splashscreen
onl oaded: {
popup.visible = false
}
visible: status == Loader.Ready
}
}
閃屏.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Window 2.2
Item {
Rectangle {
id: splashRect
anchors.fill: parent
color: "white"
border.width: 0
border.color: "black"
AnimatedImage {
id: splash
source: "qrc:/images/Rotating_earth_(large).gif"
anchors.fill: parent
}
}
}
重物件.qml
import QtQuick
Item {
function cumsum() {
for(var j=0;j<100;j ){
var p = 0
for (var i = 0; i < 1000000; i ) {
p *= i
}
}
return ""
}
// show dummy text that this is the main windows
Text {
text: "Main Window" String(cumsum())
anchors.centerIn: parent
}
}
uj5u.com熱心網友回復:
您在 QML 中所做的大多數事情都是在 QML 引擎執行緒中處理的。如果您在該執行緒中執行繁重的操作,它將阻塞其他所有內容。我還沒有檢查你的源代碼,但是,在繁重的初始化方面,我們可以用 Qt.callLater() 或類似的方法將其分解,以便 QML 引擎執行緒可以趕上 UI/UX 事件。
例如,在下面:
- 我
cumsum從一個函式變成了一個屬性 - 我介紹
calcStep了為一次j迭代進行計算 - 我
Qt.callLater用來實體化下一次迭代 - 我開始計算期間
Component.onCompleted
property string cumsum
function calcStep(j) {
if (j >= 100) {
cumsum = new Date();
return;
}
for (var i = 0; i < 1000000; i ) {
p *= i
}
Qt.callLater(calcStep, j 1);
}
Component.onCompleted: calcStep(0)
}
如果您的初始化更復雜,您可能想嘗試一下 Promises。這允許您以同步型別的方式撰寫異步例程,例如
property string cumsum
function calc() {
_asyncToGenerator(function*() {
for(var j=0;j<100;j ){
var p = 0
status = "j: " j;
yield pass();
for (var i = 0; i < 1000000; i ) {
p *= i
}
}
cumsum = new Date();
})();
}
function pass() {
return new Promise(function (resolve, reject) {
Qt.callLater(resolve);
} );
}
Component.onCompleted: calc()
在上面,cumsum計算一直使用 async/await 模式的派生。為此,我使用_asyncToGenerator了 babeljs.io 上的轉譯器提供的作業。這是必需的,因為 QML/JS 直到 Qt6.6 才支持異步/等待模式。
該pass()函式的操作與 Python pass 類似,但我的實作Qt.callLater包含在 Promise 中。呼叫它只yield pass();會讓您的函式暫時釋放控制,以便 UI/UX 事件可以趕上。
import QtQuick
import QtQuick.Controls
Page {
property string cumsum
property string status
// show dummy text that this is the main windows
Text {
text: "Main Window: " cumsum
anchors.centerIn: parent
}
Text {
text: status
anchors.horizontalCenter: parent.horizontalCenter
y: parent.height * 3 / 4
}
function calc() {
_asyncToGenerator(function*() {
for(var j=0;j<100;j ){
var p = 0
status = "j: " j;
yield pass();
for (var i = 0; i < 1000000; i ) {
p *= i
}
}
cumsum = new Date();
})();
}
function pass() {
return new Promise(function (resolve, reject) {
Qt.callLater(resolve);
} );
}
function _asyncToGenerator(fn) {
return function() {
var self = this,
args = arguments
return new Promise(function(resolve, reject) {
var gen = fn.apply(self, args)
function _next(value) {
_asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value)
}
function _throw(err) {
_asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err)
}
_next(undefined)
})
}
}
function _asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg)
var value = info.value
} catch (error) {
reject(error)
return
}
if (info.done) {
resolve(value)
} else {
Promise.resolve(value).then(_next, _throw)
}
}
Component.onCompleted: calc()
}
您可以在線試用!
如果您對我使用 async 和 QML Promises 所做的一些作業感興趣,請參閱以下 GitHub 專案:
- https://github.com/stephenquan/qt5-qml-promises
- https://github.com/stephenquan/qt5-qml-promises-demo
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/528360.html
標籤:qtqml
上一篇:讓另一個小部件處理Qt中的事件
