Using QtLocation Map with QWidget::createWindowContainer() fails to load



  • I am trying to add map functionality to my widget based application. To demonstrate the problem I am having, I will reference the minimal map example.

    The QML for drawing the map is in main.qml.

    main.qml:

    //================================
    // main.qml
    //================================
    import QtQuick 2.0
    import QtQuick.Window 2.0
    import QtLocation 5.6
    import QtPositioning 5.6
    
    Item {
        id: qmlMap
    
        Plugin {
            id: osmPlugin
            name: "osm"
        }
    
        Map {
            anchors.fill: parent
            plugin: osmPlugin
            center: QtPositioning.coordinate(59.91, 10.75) // Oslo
            zoomLevel: 10
        }
    }
    

    In order to display this QML as a widget, I create a QQuickView and set its source to qrc:/main.qml. Then I get a widget for the QQuickView using QWidget::createWindowContainer(). Finally, I add the newly created QWidget to a layout in the UI form I designed in Qt Creator. For this simple debugging demo, all it consists of is a QMainWindow with a single centralWidget, which has a child layout called qmlLayout. All this is done in mainwindow.cpp.

    mainwindow.cpp:

    //================================
    // mainwindow.cpp
    //================================
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        /* Add the QML map to the UI */
        qmlView = new QQuickView();
        qmlView->setSource(QUrl(QStringLiteral("qrc:/main.qml")));
        qmlView->show();
        QWidget *qmlWidget = QWidget::createWindowContainer(qmlView, this);
        ui->qmlLayout->addWidget(qmlWidget);
        qmlWidget->show();
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    Now, I would expect this to draw a map. Instead, a white screen is drawn where is my content?

    The real kicker, is that if I use the same code but I place it in a QQuickWidget, it loads up fine and works perfectly. Unfortunately I can't / don't want to use QQuickWidget because of its drawbacks. I am doing a lot of OpenGL rendering, and don't want to deal with the loss of threading and performance hits discussed here.

    Miscellaneous observations I have made:

    • The QML is being loaded because if I add a Rect to the root QML Item it renders properly. But if I place the same Rect inside the Map, it is not drawn.
    • I am receiving no QML errors or warnings aside from issues resolving SSL methods. These same errors appear when the map is functioning properly.

    My guesses as to why this isn't working as expected:

    • Map only works if it is the child of a Window. In order to use QQuickView::setSource() thought, the root element must be an Item (unless I am missing something).
    • Maybe if I try to initialize the QQuickView outside of main() the plugin doesn't work.

    So... what did I do wrong, or what options do I have?

    For completeness, here are the other files involved in the sample project, if you want to replicate the issue on your machine.

    qml.qrc:

    <RCC>
        <qresource prefix="/">
            <file>main.qml</file>
        </qresource>
    </RCC>
    

    main.cpp:

    //=========================
    // main.cpp
    //=========================
    #include "mainwindow.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    

    mainwindow.h:

    //========================
    // mainwindow.h
    //========================
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QQuickView>
    #include <QQmlEngine>
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
    
        QQuickView *qmlView;
    };
    
    #endif // MAINWINDOW_H
    

    mainwindow.ui

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>MainWindow</class>
     <widget class="QMainWindow" name="MainWindow">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>957</width>
        <height>636</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>MainWindow</string>
      </property>
      <widget class="QWidget" name="centralWidget">
       <layout class="QHBoxLayout" name="horizontalLayout">
        <item>
         <layout class="QVBoxLayout" name="qmlLayout"/>
        </item>
       </layout>
      </widget>
     </widget>
     <layoutdefault spacing="6" margin="11"/>
     <resources/>
     <connections/>
    </ui>
    

    widgetsMapTest.pro

    #==============================
    # widgetsMapTest.pro
    #==============================
    QT       += core gui quick location
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    TARGET = widgetsMapTest
    TEMPLATE = app
    DEFINES += QT_DEPRECATED_WARNINGS
    SOURCES += main.cpp\
            mainwindow.cpp
    HEADERS  += mainwindow.h
    FORMS    += mainwindow.ui
    RESOURCES += \
        qml.qrc
    

    TLDR: Inserting a QQuickView loaded with QWidget::createWindowContainer() and then inserting that QWidget in to a widget based UI layout results in the QtLocation Map type to failing to render. Other QML code executes properly.

    Thanks for your help =)



  • Another intersting observation, when the map works properly, I receive the following output:

    QML debugging is enabled. Only use this in a safe environment.
    qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method
    qt.network.ssl: QSslSocket: cannot resolve SSLv2_server_method
    QGeoTileProviderOsm: Tileserver disabled at  QUrl("http://maps-redirect.qt.io/osm/5.8/satellite")
    QGeoTileFetcherOsm: all providers resolved
    

    However, when it fails to work properly, I get the following:

    QML debugging is enabled. Only use this in a safe environment.
    qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method
    qt.network.ssl: QSslSocket: cannot resolve SSLv2_server_method
    

    And it hangs there, never echoing the message stating that all the providers were resolved. This would make you think that the issue then is some how related to one of the modules listed, but when I switch the plugin to use Mapbox, I get NO console output, and obviously a blank screen.

    However, if I add a callback to the Map Component.onCompleted, I can clearly see that onCompleted is called for the Map.

    The plot thickens.



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.