Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to abort loading component in Loader?

I have a Loader object that loads some very heavy components. Some event arrives in the middle of the load that requires loading to stop and go back to empty the Loader. Is it possible?

like image 745
Rinat Veliakhmedov Avatar asked Apr 12 '17 13:04

Rinat Veliakhmedov


2 Answers

Abort object creation

As documented by Qt, three methods exists to unload/abort an object instantiation:

  1. Set Loader.active to false
  2. Set Loader.source to an empty string
  3. Set Loader.sourceComponent to undefined

Asynchronous behaviour

To be able to change these properties during loading, Loader.asynchronous should be true, otherwise the GUI thread is busy with loading the object. You also need to QQmlIncubationController for your QQmlEngine to control the idle time used for object incubation. Without such a controller Loader.asynchronous does not have any effect. Note that QQmlApplicationEngine automatically installs a default controller if the scene contains a QQuickWindow.

Bugs

Up to the last tested Qt version (Qt 5.8.0, 5.9.0 beta), a severe memory leaks exist when aborting an unfinished object incubation (at least in certain cases, including the example in the answer of derM) resulting in a fast memory usage increase for large components. A bug report is created including a proposed solution.

According to the bug report, this should be fixed in Qt version 5.15 (not tested).

like image 72
m7913d Avatar answered Nov 07 '22 09:11

m7913d


I don't know what your issu is, with those objects that are destroyed before the loader finishs, but maybe the issue is there? If not, this should work: If it does not help, please add some code to your question, that reproduces your problem.

main.qml

import QtQuick 2.7
import QtQuick.Controls 2.0

ApplicationWindow {
    id: root
    visible: true
    width: 400; height: 450

    Button {
        text: (complexLoader.active ? 'Loading' : 'Unloading')
        onClicked: complexLoader.active = !complexLoader.active
    }

    Loader {
        id: complexLoader
        y: 50
        width: 400
        height: 400
        source: 'ComplexComponent.qml'
        asynchronous: true
        active: false
        // visible: status === 1
    }

    BusyIndicator {
        anchors.fill: complexLoader
        running: complexLoader.status === 2
        visible: running
    }
}

ComplexComponent.qml

import QtQuick 2.0

Rectangle {
    id: root
    width: 400
    height: 400
    Grid {
        id: grid
        anchors.fill: parent
        rows: 50
        columns: 50
        Repeater {
            model: parent.rows * parent.columns
            delegate: Rectangle {
                width: root.width / grid.columns
                height: root.height / grid.rows
                color: Qt.rgba(Math.random(index),
                               Math.random(index),
                               Math.random(index),
                               Math.random(index))
            }
        }
    }
}
like image 40
derM Avatar answered Nov 07 '22 11:11

derM