convert threading example to manual tests
The threading example used a LauncherList to combine two different but related examples into one. I've now separated both into a shared directory called 'threading' Pick-to: 6.6 Change-Id: Iee8898e61adcf69dc67157a1eff5f6ac019a39ca Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
parent
add2620e2e
commit
38373b81f3
|
@ -19,7 +19,6 @@ qt_internal_add_example(positioners)
|
|||
add_subdirectory(scenegraph)
|
||||
qt_internal_add_example(shadereffects)
|
||||
qt_internal_add_example(text)
|
||||
qt_internal_add_example(threading)
|
||||
add_subdirectory(tutorials)
|
||||
add_subdirectory(customitems)
|
||||
qt_internal_add_example(imageprovider)
|
||||
|
@ -48,7 +47,6 @@ set(reused_dir_targets
|
|||
views_shared
|
||||
positioners_shared
|
||||
text_shared
|
||||
threading_shared
|
||||
window_shared
|
||||
shapes_shared
|
||||
imageelements_shared
|
||||
|
|
|
@ -18,7 +18,6 @@ SUBDIRS = quick-accessibility \
|
|||
scenegraph \
|
||||
shadereffects \
|
||||
text \
|
||||
threading \
|
||||
tutorials \
|
||||
customitems \
|
||||
imageprovider \
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(threading LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/quick/threading")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
add_subdirectory("../shared" "shared")
|
||||
|
||||
qt_add_executable(threadingexample
|
||||
WIN32
|
||||
MACOSX_BUNDLE
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(threadingexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Qml
|
||||
Qt6::Quick
|
||||
)
|
||||
|
||||
add_dependencies(threadingexample threading_shared)
|
||||
|
||||
qt_add_qml_module(threadingexample
|
||||
URI threading
|
||||
QML_FILES
|
||||
"threadedlistmodel/dataloader.mjs"
|
||||
"threadedlistmodel/timedisplay.qml"
|
||||
"threading.qml"
|
||||
"workerscript/Spinner.qml"
|
||||
"workerscript/workerscript.mjs"
|
||||
"workerscript/workerscript.qml"
|
||||
)
|
||||
|
||||
install(TARGETS threadingexample
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
||||
|
||||
bundle_shared(threadingexample)
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB |
|
@ -1,44 +0,0 @@
|
|||
// Copyright (C) 2017 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||
/*!
|
||||
\title Qt Quick Examples - Threading
|
||||
\example threading
|
||||
\brief This is a collection of QML multithreading examples.
|
||||
\image qml-threading-example.png
|
||||
\ingroup qtquickexamples
|
||||
|
||||
\e Threading is a collection of QML multithreading examples.
|
||||
|
||||
\include examples-run.qdocinc
|
||||
|
||||
\section1 Threaded ListModel
|
||||
|
||||
\e{Threaded ListModel} contains a \l ListView and a \l ListModel.
|
||||
The ListModel object is updated asynchronously in another thread, and the
|
||||
results propagate back to the main thread. A timer requests updates from the
|
||||
worker thread periodically:
|
||||
\snippet threading/threadedlistmodel/timedisplay.qml 0
|
||||
|
||||
Inside the worker thread, the ListModel is synchronized once the data is
|
||||
finished loading:
|
||||
\snippet threading/threadedlistmodel/dataloader.mjs 0
|
||||
|
||||
\section1 WorkerScript
|
||||
|
||||
\e WorkerScript contains an example of using a \l WorkerScript to offload
|
||||
expensive calculations into another thread. This keeps the UI from being
|
||||
blocked. This example calculates numbers in Pascal's Triangle, and not in a
|
||||
very optimal way, so it will often take several seconds to complete the
|
||||
calculation. By doing this in a WorkerScript in another thread, the UI is
|
||||
not blocked during this time.
|
||||
|
||||
When the UI needs another value, a request is sent to the WorkerScript:
|
||||
\snippet threading/workerscript/workerscript.qml 0
|
||||
|
||||
The workerscript then is free to take a really long time to calculate it:
|
||||
\snippet threading/workerscript/workerscript.mjs 0
|
||||
|
||||
When it's done, the result returns to the main scene via the WorkerScript
|
||||
type:
|
||||
\snippet threading/workerscript/workerscript.qml 1
|
||||
*/
|
|
@ -1,4 +0,0 @@
|
|||
// Copyright (C) 2017 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
#include "../shared/shared.h"
|
||||
DECLARATIVE_EXAMPLE_MAIN(threading/threading)
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (C) 2017 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||
|
||||
/*!
|
||||
\title Threaded ListModel Example
|
||||
\example threading/threadedlistmodel
|
||||
\brief The Threaded ListModel example shows how to use a ListModel from multiple
|
||||
threads using WorkerScript.
|
||||
|
||||
This example shows how to use a ListModel from multiple threads using
|
||||
WorkerScript.
|
||||
*/
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (C) 2017 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
import QmlProject 1.1
|
||||
|
||||
Project {
|
||||
mainFile: "timedisplay.qml"
|
||||
|
||||
/* Include .qml, .js, and image files from current directory and subdirectories */
|
||||
QmlFiles {
|
||||
directory: "."
|
||||
}
|
||||
JavaScriptFiles {
|
||||
directory: "."
|
||||
}
|
||||
ImageFiles {
|
||||
directory: "."
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
TEMPLATE = app
|
||||
|
||||
QT += quick qml
|
||||
SOURCES += main.cpp
|
||||
RESOURCES += \
|
||||
threading.qrc \
|
||||
../shared/shared.qrc
|
||||
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/quick/threading
|
||||
INSTALLS += target
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright (C) 2017 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
import QtQuick
|
||||
import shared as Examples
|
||||
|
||||
Item {
|
||||
height: 480
|
||||
width: 320
|
||||
Examples.LauncherList {
|
||||
id: ll
|
||||
anchors.fill: parent
|
||||
Component.onCompleted: {
|
||||
addExample("Threaded ListModel", "Updates a ListModel in another thread", Qt.resolvedUrl("threadedlistmodel/timedisplay.qml"));
|
||||
addExample("WorkerScript", "Performs calculations in another thread", Qt.resolvedUrl("workerscript/workerscript.qml"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import QmlProject 1.1
|
||||
|
||||
Project {
|
||||
mainFile: "threading.qml"
|
||||
importPaths: ["../"]
|
||||
|
||||
/* Include .qml, .js, and image files from current directory and subdirectories */
|
||||
QmlFiles {
|
||||
directory: "."
|
||||
}
|
||||
JavaScriptFiles {
|
||||
directory: "."
|
||||
}
|
||||
ImageFiles {
|
||||
directory: "."
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<RCC>
|
||||
<qresource prefix="/qt/qml/threading">
|
||||
<file>threading.qml</file>
|
||||
<file>threadedlistmodel/timedisplay.qml</file>
|
||||
<file>threadedlistmodel/dataloader.mjs</file>
|
||||
<file>workerscript/Spinner.qml</file>
|
||||
<file>workerscript/workerscript.mjs</file>
|
||||
<file>workerscript/workerscript.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (C) 2017 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
import QmlProject 1.1
|
||||
|
||||
Project {
|
||||
mainFile: "workerscript.qml"
|
||||
|
||||
/* Include .qml, .js, and image files from current directory and subdirectories */
|
||||
QmlFiles {
|
||||
directory: "."
|
||||
}
|
||||
JavaScriptFiles {
|
||||
directory: "."
|
||||
}
|
||||
ImageFiles {
|
||||
directory: "."
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (C) 2017 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
import QtQuick
|
||||
|
||||
Rectangle {
|
||||
color: "white"
|
||||
width: 200
|
||||
height: 300
|
||||
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
model: listModel
|
||||
delegate: Component {
|
||||
Text {
|
||||
required property string time
|
||||
text: time
|
||||
}
|
||||
}
|
||||
|
||||
ListModel { id: listModel }
|
||||
|
||||
WorkerScript {
|
||||
id: worker
|
||||
source: "dataloader.mjs"
|
||||
}
|
||||
|
||||
// ![0]
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 2000; repeat: true
|
||||
running: true
|
||||
triggeredOnStart: true
|
||||
|
||||
onTriggered: {
|
||||
var msg = {'action': 'appendCurrentTime', 'model': listModel};
|
||||
worker.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
// ![0]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (C) 2017 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
// ![0]
|
||||
WorkerScript.onMessage = function(msg) {
|
||||
if (msg.action == 'appendCurrentTime') {
|
||||
var data = {'time': new Date().toTimeString()};
|
||||
msg.model.append(data);
|
||||
msg.model.sync(); // updates the changes to the list
|
||||
}
|
||||
}
|
||||
// ![0]
|
||||
|
|
@ -1981,7 +1981,7 @@ void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
|
|||
|
||||
\section1 Using Threaded List Models with WorkerScript
|
||||
|
||||
ListModel can be used together with WorkerScript access a list model
|
||||
ListModel can be used together with WorkerScript to access a list model
|
||||
from multiple threads. This is useful if list modifications are
|
||||
synchronous and take some time: the list operations can be moved to a
|
||||
different thread to avoid blocking of the main GUI thread.
|
||||
|
@ -1989,11 +1989,11 @@ void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
|
|||
Here is an example that uses WorkerScript to periodically append the
|
||||
current time to a list model:
|
||||
|
||||
\snippet ../../examples/quick/threading/threadedlistmodel/timedisplay.qml 0
|
||||
\snippet qml/listmodel/WorkerScript.qml 0
|
||||
|
||||
The included file, \tt dataloader.mjs, looks like this:
|
||||
|
||||
\snippet ../../examples/quick/threading/threadedlistmodel/dataloader.mjs 0
|
||||
\snippet qml/listmodel/dataloader.mjs 0
|
||||
|
||||
The timer in the main example sends messages to the worker script by calling
|
||||
\l WorkerScript::sendMessage(). When this message is received,
|
||||
|
@ -2004,7 +2004,7 @@ void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
|
|||
You must call sync() or else the changes made to the list from that
|
||||
thread will not be reflected in the list model in the main thread.
|
||||
|
||||
\sa {qml-data-models}{Data Models}, {Qt Quick Examples - Threading}, {Qt QML}
|
||||
\sa {qml-data-models}{Data Models}, {Qt QML}
|
||||
*/
|
||||
|
||||
QQmlListModel::QQmlListModel(QObject *parent)
|
||||
|
|
|
@ -508,9 +508,6 @@ void QQuickWorkerScriptEngine::run()
|
|||
|
||||
Worker scripts that are plain JavaScript sources can not use \l {qtqml-javascript-imports.html}{.import} syntax.
|
||||
Scripts that are ECMAScript modules can freely use import and export statements.
|
||||
|
||||
\sa {Qt Quick Examples - Threading},
|
||||
{Threaded ListModel Example}
|
||||
*/
|
||||
QQuickWorkerScript::QQuickWorkerScript(QObject *parent)
|
||||
: QObject(parent), m_engine(nullptr), m_scriptId(-1), m_componentComplete(true)
|
||||
|
|
|
@ -92,8 +92,7 @@ imagedirs += images
|
|||
excludefiles += ../util/qquickpropertychanges_p.h
|
||||
examples.fileextensions += "*.qm"
|
||||
|
||||
manifestmeta.thumbnail.names += "QtQuick/Threaded ListModel Example" \
|
||||
"QtQuick/QML Dynamic View Ordering Tutorial*"
|
||||
manifestmeta.thumbnail.names += "QtQuick/QML Dynamic View Ordering Tutorial*"
|
||||
|
||||
manifestmeta.highlighted.names = "QtQuick/Qt Quick Demo - Same Game"
|
||||
|
||||
|
|
|
@ -138,7 +138,6 @@ Creator.
|
|||
\div {class="doc-column"}
|
||||
\b{System and Events}
|
||||
\list
|
||||
\li \l{Qt Quick Examples - Threading}{Threading}
|
||||
\li \l{Qt Quick Examples - Accessibility}{Accessibility}
|
||||
\li \l{Qt Quick Examples - externaldraganddrop}{External Drag and Drop}
|
||||
\li \l{Qt Quick Examples - Drag and Drop}{Drag and Drop}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
"quick/externaldraganddrop Example", "examples/quick/externaldraganddrop", "externaldraganddrop", 0, -1
|
||||
"quick/customitems/maskedmousearea Example", "examples/quick/customitems/maskedmousearea", "maskedmousearea", 0, -1
|
||||
"quick/imageelements Example", "examples/quick/imageelements", "imageelements", 0, -1
|
||||
"quick/threading Example", "examples/quick/threading", "threading", 0, -1
|
||||
"quick/scenegraph/openglunderqml Example", "examples/quick/scenegraph/openglunderqml", "openglunderqml", 0, -1
|
||||
"quick/scenegraph/threadedanimation Example", "examples/quick/scenegraph/threadedanimation", "threadedanimation", 0, -1
|
||||
"quick/scenegraph/twotextureproviders Example", "examples/quick/scenegraph/twotextureproviders", "twotextureproviders", 0, -1
|
||||
|
|
|
@ -14,6 +14,7 @@ add_subdirectory(shapestest)
|
|||
add_subdirectory(tableview)
|
||||
add_subdirectory(text)
|
||||
add_subdirectory(touch)
|
||||
add_subdirectory(threading)
|
||||
# add_subdirectory(v4) # TODO: port if needed
|
||||
add_subdirectory(quickcontrols)
|
||||
add_subdirectory(quickdialogs)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
add_subdirectory(threading)
|
||||
add_subdirectory(workerscript)
|
|
@ -0,0 +1,33 @@
|
|||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(threadedlistmodel LANGUAGES C CXX ASM)
|
||||
find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
|
||||
endif()
|
||||
|
||||
qt_internal_add_manual_test(tst_manual_threadedlistmodel
|
||||
GUI
|
||||
SOURCES
|
||||
threadedlistmodel.cpp
|
||||
DEFINES
|
||||
QT_DEPRECATED_WARNINGS
|
||||
LIBRARIES
|
||||
Qt::Gui
|
||||
Qt::Qml
|
||||
Qt::Quick
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(qmake_immediate_resource_files
|
||||
timedisplay.qml
|
||||
dataloader.mjs
|
||||
)
|
||||
|
||||
qt_internal_add_resource(tst_manual_threadedlistmodel "qmake_immediate"
|
||||
PREFIX
|
||||
"/qt/qml/threadedlistmodel"
|
||||
FILES
|
||||
${qmake_immediate_resource_files}
|
||||
)
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (C) 2021 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtQuick/QQuickView>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QCoreApplication::setApplicationName("threadedlistmodel-manual-test");
|
||||
QCoreApplication::setOrganizationName("QtProject");
|
||||
|
||||
QQuickView view;
|
||||
view.setSource(QUrl(QStringLiteral("qrc:/qt/qml/threadedlistmodel/timedisplay.qml")));
|
||||
view.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
TEMPLATE = app
|
||||
TARGET = threadedlistmodel
|
||||
QT += qml quick
|
||||
|
||||
SOURCES += threadedlistmodel.cpp
|
||||
RESOURCES += threadedlistmodel.qrc
|
|
@ -0,0 +1,5 @@
|
|||
<RCC>
|
||||
<qresource prefix="/qt/qml/threadedlistmodel">
|
||||
<file>timedisplay.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -0,0 +1,34 @@
|
|||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(workerscript LANGUAGES C CXX ASM)
|
||||
find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
|
||||
endif()
|
||||
|
||||
qt_internal_add_manual_test(tst_manual_workerscript
|
||||
GUI
|
||||
SOURCES
|
||||
workerscript.cpp
|
||||
DEFINES
|
||||
QT_DEPRECATED_WARNINGS
|
||||
LIBRARIES
|
||||
Qt::Gui
|
||||
Qt::Qml
|
||||
Qt::Quick
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(qmake_immediate_resource_files
|
||||
"Spinner.qml"
|
||||
"workerscript.qml"
|
||||
"workerscript.mjs"
|
||||
)
|
||||
|
||||
qt_internal_add_resource(tst_manual_workerscript "qmake_immediate"
|
||||
PREFIX
|
||||
"/qt/qml/workerscript"
|
||||
FILES
|
||||
${qmake_immediate_resource_files}
|
||||
)
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (C) 2021 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtQuick/QQuickView>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QCoreApplication::setApplicationName("workerscript-manual-test");
|
||||
QCoreApplication::setOrganizationName("QtProject");
|
||||
|
||||
QQuickView view;
|
||||
view.setSource(QUrl(QStringLiteral("qrc:/qt/qml/workerscript/workerscript.qml")));
|
||||
view.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
TEMPLATE = app
|
||||
TARGET = workerscript
|
||||
QT += qml quick
|
||||
|
||||
SOURCES += workerscript.cpp
|
||||
RESOURCES += workerscript.qrc
|
|
@ -6,7 +6,6 @@ import QtQuick
|
|||
Rectangle {
|
||||
width: 320; height: 480
|
||||
|
||||
//! [1]
|
||||
WorkerScript {
|
||||
id: myWorker
|
||||
source: "workerscript.mjs"
|
||||
|
@ -20,12 +19,12 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
//! [1]
|
||||
|
||||
Row {
|
||||
y: 24
|
||||
spacing: 24
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
//! [0]
|
||||
|
||||
Spinner {
|
||||
id: rowSpinner
|
||||
label: "Row"
|
||||
|
@ -34,7 +33,6 @@ Rectangle {
|
|||
myWorker.sendMessage( { row: rowSpinner.value, column: columnSpinner.value } );
|
||||
}
|
||||
}
|
||||
//! [0]
|
||||
|
||||
Spinner {
|
||||
id: columnSpinner
|
|
@ -0,0 +1,7 @@
|
|||
<RCC>
|
||||
<qresource prefix="/qt/qml/workerscript">
|
||||
<file>Spinner.qml</file>
|
||||
<file>workerscript.mjs</file>
|
||||
<file>workerscript.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
Loading…
Reference in New Issue