Unsolved Using Scene3D and Surface3D in the same .qml object results in a warning on program exit
-
Hello everyone!
I have Scene3D and Surface3D elements on my main.qml. When program exits I get warning: "Attempting to create QWindow-based QOffscreenSurface outside the gui thread. Expect failures.". Everything else is OK.
The warning disappears when I comment out either Scene3D {...} or Surface3D {...}. I suppose the reason is the sequence of thread destruction (?) or something like that. Google says nothing about that, except the source code of Qt:
qoffscreensurface.cpp:
... if (QThread::currentThread() != qGuiApp->thread()) qWarning("Attempting to create QWindow-based QOffscreenSurface outside the gui thread. Expect failures."); ...
I do not create any additional threads in my application, so I suppose the reason is that either QThread::currentThread() or qGuiApp->thread() is 0 at that moment (when program exits).
How to avoid this warning?
-
Please attach how you set up your code (the C++ part) and perhaps also a stripped down version of your QML file.
-
main.cpp
#include <QtWidgets/QApplication> #include <QtQml/QQmlContext> #include <QtQuick/QQuickView> #include <QtQml/QQmlEngine> #include <QtCore/QDir> #include <QNetworkInterface> #include <QComboBox> #include <QObject> #include "datasource.h" #include "tssocket.h" #include "address_provider.h" #include "intercom.h" #include "ipslistmodel.h" #include "interfacehelper.h" #include "measurementmodel.h" #include <QtQml> #include "timeline3d.h" int main(int argc, char *argv[]) { qDebug() << QThread::currentThreadId(); // Qt Charts uses Qt Graphics View Framework for drawing, therefore QApplication must be used. QApplication app(argc, argv); qmlRegisterType<IPsListModel>("IPsListModel", 1, 0, "IPsListModel"); qmlRegisterType<Timeline3D>("com.example.Timeline3D", 1, 0, "Timeline3D"); QQuickView viewer; // The following are needed to make examples run without having to install the module // in desktop environments. #ifdef Q_OS_WIN QString extraImportPath(QStringLiteral("%1/../../../../%2")); #else QString extraImportPath(QStringLiteral("%1/../../../%2")); #endif viewer.engine()->addImportPath(extraImportPath.arg(QGuiApplication::applicationDirPath(), QString::fromLatin1("qml"))); QObject::connect(viewer.engine(), &QQmlEngine::quit, &viewer, &QWindow::close); viewer.setTitle(QStringLiteral("Scan Tube v0.0")); DataSource dataSource(&viewer); viewer.rootContext()->setContextProperty("dataSource", &dataSource); intercom *_intercom = new intercom(&viewer); _intercom->setDataSource(&dataSource); viewer.rootContext()->setContextProperty("_intercom", _intercom); InterfaceHelper *_interfaceHelper = new InterfaceHelper(); viewer.rootContext()->setContextProperty("_interfaceHelper", _interfaceHelper); IPsListModel myIPsListModel; foreach (const QHostAddress &address, QNetworkInterface::allAddresses()) { if (address.protocol() == QAbstractSocket::IPv4Protocol && address != QHostAddress(QHostAddress::LocalHost) && !address.isLoopback()){ qDebug() << address.toString(); myIPsListModel.add(address.toString()); } } viewer.rootContext()->setContextProperty("myIPsListModel", &myIPsListModel); MeasurementModel measurementModel; viewer.rootContext()->setContextProperty("measurementModel", &measurementModel); dataSource.setMeasurementModel(&measurementModel); viewer.setSource(QUrl("qrc:/qml/qmloscilloscope/main.qml")); viewer.setResizeMode(QQuickView::SizeRootObjectToView); viewer.setColor(QColor("#404040")); viewer.show(); auto ret = app.exec(); _intercom->off(); return ret; }
timeline3d.h
#ifndef TIMELINE3D_H #define TIMELINE3D_H #include <QObject> #include <Qt3DCore> #include <Qt3DRender> #include <Qt3DExtras> #include "datasource.h" using namespace Qt3DCore; using namespace Qt3DRender; using namespace Qt3DExtras; class Timeline3D : public QEntity { Q_OBJECT public: Timeline3D(QNode *parent = 0); Q_INVOKABLE void addScan(); Q_INVOKABLE void connectDataSource(DataSource *dataSource); private: DataSource *dataSource {nullptr}; QCamera *m_camera; Qt3DCore::QTransform *lightTransform; int m_count; float x,y; void onTimerUpdate(); //QPlaneMesh* m_planeMesh; QPhongAlphaMaterial *m_planeMaterial; Qt3DRender::QBuffer *vertexBuffer; QAttribute *positionAttribute; //todo temporary, remove QGeometryRenderer* m_geometryRenderer; void addPoint(); }; #endif // TIMELINE3D_H
timeline3d.cpp
#include <Qt3DInput> #include "timeline3d.h" #define ANGLE 13 #define COUNT 8 Timeline3D::Timeline3D(QNode *parent) : QEntity(parent) , m_camera(new QCamera()) , m_count(0) , y(0.0f) , x(0.0f) { m_camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f); // FrameGraph QRenderSettings *renderSettings = new QRenderSettings(); QRenderSurfaceSelector *renderSurfaceSelector = new QRenderSurfaceSelector(); QViewport *viewport = new QViewport(); viewport->setNormalizedRect(QRectF(0.0f, 0.0f, 1.0f, 1.0f)); QLayerFilter *layerFilter = new QLayerFilter(); layerFilter->setEnabled(false); QCameraSelector *cameraSelector = new QCameraSelector(); cameraSelector->setCamera(m_camera); QClearBuffers *clearBuffer = new QClearBuffers(); clearBuffer->setBuffers(QClearBuffers::ColorDepthStencilBuffer); clearBuffer->setClearColor("black"); clearBuffer->setParent(cameraSelector); cameraSelector->setParent(layerFilter); layerFilter->setParent(renderSurfaceSelector); renderSurfaceSelector->setParent(viewport); renderSettings->setActiveFrameGraph(viewport); this->addComponent(renderSettings); m_camera->setPosition(QVector3D(0.0f,5.0f,0.0f) + QVector3D(-25.0f,0.0f,0.0f)); m_camera->setViewCenter(QVector3D(0.0f,0.0f,0.0f)); m_camera->setUpVector(QVector3D(0.0f,1.0f,0.0f)); //phong alpha 0.3 material m_planeMaterial = new QPhongAlphaMaterial(); m_planeMaterial->setAmbient(QColor(100,100,100)); m_planeMaterial->setDiffuse(QColor(255,255,255)); m_planeMaterial->setAlpha(0.3f); QTimer *timer = new QTimer(); QObject::connect(timer, &QTimer::timeout,this,&Timeline3D::onTimerUpdate); timer->start(100); Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity(this); Qt3DRender::QPointLight *light = new Qt3DRender::QPointLight(lightEntity); light->setColor("yellow"); light->setIntensity(1000); lightEntity->addComponent(light); lightTransform = new Qt3DCore::QTransform(lightEntity); lightTransform->setTranslation(QVector3D(0, 0, 0)); lightEntity->addComponent(lightTransform); //m_camera->setPosition(QVector3D(y,sinf(M_PI/12)*30.0f,x+50.0f)); //m_camera->setViewCenter(QVector3D(y,0.0f,x)); } void Timeline3D::addScan() { if (!dataSource) return; auto scan_data = dataSource->getScanData(); if (!scan_data) return; } void Timeline3D::connectDataSource(DataSource *dataSource) { this->dataSource = dataSource; } void Timeline3D::addPoint() { float* reVertexArray; x -= 5.0f; y += qrand() % 2 - 1; if (!(m_count % 100)) { //every 100-th timer tick: m_geometryRenderer = new QGeometryRenderer(); QGeometry* meshGeometry = new QGeometry(m_geometryRenderer); QByteArray vertexArray; vertexArray.resize(200*3*sizeof(float)); reVertexArray = reinterpret_cast<float*>(vertexArray.data()); //coordinates of left vertex reVertexArray[0] = y-5.0f; reVertexArray[1] = 0.0f; reVertexArray[2] = x; //coordinates of right vertex reVertexArray[3] = y+5.0f; reVertexArray[4] = 0.0f; reVertexArray[5] = x; vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer,meshGeometry); vertexBuffer->setUsage(Qt3DRender::QBuffer::DynamicDraw); vertexBuffer->setData(vertexArray); // Attributes positionAttribute = new QAttribute(meshGeometry); positionAttribute->setAttributeType(QAttribute::VertexAttribute); positionAttribute->setBuffer(vertexBuffer); positionAttribute->setDataType(QAttribute::Float); positionAttribute->setDataSize(3); positionAttribute->setByteOffset(0); positionAttribute->setByteStride(3*sizeof(float)); positionAttribute->setCount(2); positionAttribute->setName(QAttribute::defaultPositionAttributeName()); meshGeometry->addAttribute(positionAttribute); m_geometryRenderer->setInstanceCount(1); m_geometryRenderer->setFirstVertex(0); m_geometryRenderer->setFirstInstance(0); m_geometryRenderer->setPrimitiveType(QGeometryRenderer::TriangleStrip); m_geometryRenderer->setGeometry(meshGeometry); QEntity* entity = new QEntity(this); entity->addComponent(m_geometryRenderer); entity->addComponent(m_planeMaterial); return; } //update geometry QByteArray appendVertexArray; appendVertexArray.resize(2*3*sizeof(float)); reVertexArray = reinterpret_cast<float*>(appendVertexArray.data()); //coordinates of left vertex reVertexArray[0] = y-5.0f; reVertexArray[1] = 0.0f; reVertexArray[2] = x; //coordinates of right vertex reVertexArray[3] = y+5.0f; reVertexArray[4] = 1.0f; reVertexArray[5] = x; uint vertexCount = positionAttribute->count(); vertexBuffer->updateData(vertexCount*3*sizeof(float),appendVertexArray); positionAttribute->setCount(vertexCount+2); } void Timeline3D::onTimerUpdate() { addPoint(); m_camera->setPosition(QVector3D(y,sinf(M_PI/12)*30.0f,x+50.0f)); m_camera->setViewCenter(QVector3D(y,0.0f,x)); qDebug() << "x=" << x << "; y=" << y; lightTransform->setTranslation(QVector3D(y, 10.0f, x)); m_count++; }
main.qml
... StackLayout { width: parent.width height: parent.height - tabBar.height currentIndex: tabBar.currentIndex Item {...} Item {...} Item { id: timeline_3d anchors.fill: parent Scene3D { anchors.fill: parent focus: true Timeline3D { id: timeline_3d_object } } Item { id: timeline_3d_surface anchors.fill: parent Surface3D { id: timeline_3d_surface_object anchors.fill: parent axisX.min: 0.0 axisX.max: 100.0 axisX.title: "Scan" axisX.titleVisible: true axisZ.min: 0.0 axisZ.max: 727.0 axisZ.title: "Distance" axisZ.titleVisible: true axisY.min: -1024 axisY.max: 1024 axisY.title: "Signal level" axisY.titleVisible: true horizontalAspectRatio: 2 } } } ...
-
I couldn't see anything obvious, but you really should've included only the essential c++ code ...
Anyway, my best advice is to cut away everything that's not directly related to the problem, which would include all your custom classes, models and so on and see if it continues to manifest itself. Also take a look at the comments of this ticket, which may be related. It might also be helpful to get the stack trace (at the moment the warning's emitted) and see where all this started. -
Hi! Does this also happen when you put the items in a RowLayout, so that they are both visible?
-
@Wieland yes, it doesn't matter if one of them is invisible or not
-
How to get the stack trace at the moment the warning' emitted? The code with the warning is in qt's source files, I use dll's, I cannot just put breakpoint there.