Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Strange behaviour when open QML Popup Window from C++ code.

Strange behaviour when open QML Popup Window from C++ code.

Scheduled Pinned Locked Moved Solved General and Desktop
4 Posts 1 Posters 3.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • DongD Offline
    DongD Offline
    Dong
    wrote on last edited by
    #1

    Hi everyone !
    I'm implement M-V-VM Pattern and have this Strange Behaviour

    First, I open a main window like normal. then set the Context Object like this:

    //Set Data Context to the Root Context
    QObject* mainViewModel = new MainWindowViewModel(window);
    QQmlContext* ctx = engine.rootContext();
    ctx->setContextObject(mainViewModel);
    

    Then I'm try to open Popup in MainWindowViewModel like this:

    QQmlApplicationEngine engine;
    
    QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/FrmAuthenticate.qml")));
    QObject *childItem = qobject_cast<QObject*>(component.create());
    QQuickWindow *dialog = qobject_cast<QQuickWindow *>(childItem);
    QQmlContext* ctx = engine.contextForObject(dialog);
    FrmAuthenticateViewModel *viewModel = new FrmAuthenticateViewModel(dialog);
    ctx->setContextObject(viewModel);
    childItem->setParent(this->parent());
    

    in Popup I have a WebView and it print out - console.log() - each time it navigate to new Url.

    First strange thing:

    • If open the popup by create a component from QML, I got the log data.
      But when open from ViewModel, No log data print to Application Output (Can't debug in QML too)

    Second strange thing:

    • In the code to open popup above, I cannot set the contextObject for the Popup.
      It show a warning "Cannot set context object for internal context" at runtime and QML cannot call to ViewModel's functions

    Third strange thing:

    • If open the popup by code in ViewModel without set the contextObject. Webview load & display the default page.
      When trying to set contextObject. Webview cannot load & display the default page.

    Anyone have any ideal why this happen ?!

    Thanks & Best Regards
    DongLD

    1 Reply Last reply
    0
    • DongD Offline
      DongD Offline
      Dong
      wrote on last edited by
      #2

      Please... anyone can help me with this ?!

      Just open a popup from C++ & setContextObject for it.

      1 Reply Last reply
      0
      • DongD Offline
        DongD Offline
        Dong
        wrote on last edited by Dong
        #3

        I'm try to build simple sample. Don't know why, but it work (mostly)

        • I can set context object to component
        • I can get a property from context by calling View Model's binding function
        • But I can't "connect" the signal from Qml to C++ functions like main.qml call to showLoginDialog() function
          • It look like all signals in Qml wasn't fired. (No focus highlight, button onClicked not fired...

        Here is the code:

        main.qml

        import QtQuick 2.3
        import QtQuick.Controls 1.2
        
        ApplicationWindow {
            id : mainWindow
            visible: true
            width: 640
            height: 480
            title: qsTr("Hello World")
        
            menuBar: MenuBar {
                Menu {
                    title: qsTr("File")
                    MenuItem {
                        text: qsTr("&Open")
                        onTriggered:
                        {
                            //Show popup from ViewModel (C++)
                            showLoginDialog();
        
                            //Show popup from QML
        //                    var component = Qt.createComponent("qrc:/login.qml");
        //                    if (component.status == Component.Ready)
        //                    {
        //                        component.createObject(mainWindow);
        //                    }
                        }
                    }
                    MenuItem {
                        text: qsTr("Exit")
                        onTriggered: Qt.quit();
                    }
                }
            }
        }
        
        

        main.cpp

        int main(int argc, char *argv[])
        {
            QApplication app(argc, argv);
        
            QQmlApplicationEngine engine;
            engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        
            QObject *topLevel = engine.rootObjects().at(0);
            QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
        
            //Set Data Context to the Root Context
            QObject* mainViewModel = new MainWindowViewModel(window);
            QQmlContext* ctx = engine.rootContext();
            ctx->setContextObject(mainViewModel);
        }
        

        mainwindowviewmodel.cpp

        #include "mainwindowviewmodel.h"
        
        MainWindowViewModel::MainWindowViewModel(QObject *parent) : QObject(parent)
        {
        
        }
        
        void MainWindowViewModel::showLoginDialog()
        {
            qDebug() << "Show Login Form";
        
            LoginViewModel *viewModel = new LoginViewModel();
            viewModel->setProperty("sampleText", "https://google.com");
            QQmlApplicationEngine engine;
        
            QQmlContext* ctx = new QQmlContext(engine.rootContext());
            ctx->setContextObject(viewModel);
        
            QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/login.qml")));
            QObject *childItem = qobject_cast<QObject*>(component.create(ctx));
            //QQuickWindow *dialog = qobject_cast<QQuickWindow *>(childItem);
        
            //FrmAuthenticateViewModel *viewModel = new FrmAuthenticateViewModel(dialog);
            childItem->setParent(this->parent());
        }
        

        login.qml

        import QtQuick 2.4
        import QtQuick.Controls 1.3
        import QtQuick.Layouts 1.1
        import QtWebKit 3.0
        //import QtWebView 1.0
        import QtTest 1.0
        
        ApplicationWindow {
            id: loginDialog
            title: qsTr("Hello World")
            width: 480
            height: 550
            visible: true
        
                TextField {
                    id: txtUrl
                    height: 30
                    text: binding("sampleText");
                    anchors.right: parent.right
                    anchors.rightMargin: 100
                    anchors.left: parent.left
                    anchors.leftMargin: 0
                    anchors.top: parent.top
                    anchors.topMargin: 0
                }
        
                Button {
                    id : btn1
                    width: 100
                    height: 30
                    text: "Go"
                    anchors.top: parent.top
                    anchors.topMargin: 0
                    anchors.right: parent.right
                    anchors.rightMargin: 0
                    onClicked:
                    {
                        text : binding("sampleText");
                    }
                }
        }
        

        loginviewmodel.cpp

        #include "loginviewmodel.h"
        
        LoginViewModel::LoginViewModel(QObject *parent) : QObject(parent)
        {
        
        }
        
        QVariant LoginViewModel::binding(const QString &propPath) const
        {
            return this->property(qPrintable(propPath));
        }
        
        QVariant LoginViewModel::getAuthenCode(const QString &message) const
        {
            qDebug() << message;
        }
        

        PS: "Tiếng tôi vang rừng núi... sao không ai trả lời"

        1 Reply Last reply
        0
        • DongD Offline
          DongD Offline
          Dong
          wrote on last edited by Dong
          #4

          I'm try to do everything in main.cpp like this... and it work fine.

          int main(int argc, char *argv[])
          {
              QApplication app(argc, argv);
          
              QQmlApplicationEngine engine;
              engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
          
              QObject *topLevel = engine.rootObjects().at(0);
              QQuickWindow *window = qobject_cast<QQuickWindow*>(topLevel);
          
              LoginViewModel *viewModel = new LoginViewModel();
              viewModel->setProperty("url", "<AuthenticationUrl>");
          
              QQmlContext *ctx = new QQmlContext(engine.rootContext());
              ctx->setContextObject(viewModel);
          
              QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/login.qml")));
              QObject *childItem = component.create(ctx);
              childItem->setParent(window);
          
              MainWindowViewModel *mainViewModel = new MainWindowViewModel(window);
              QQmlContext *mainContext = engine.rootContext();
              mainContext->setContextObject(mainViewModel);
          
              return app.exec();
          }
          

          After investigation, I found out the root cause is :
          QQmlApplicationEngine engine is not singleton. it completely different instance.

          So, I try to keep track the engine created from the main.cpp
          but QQmlApplicationEngine is Q_DISABLE_COPY
          Then, I create a class (ApplicationContext) with static RootContext object to store the mainContext.

          Then any time I need the "Root Engine", I get it from RootContext like this:

          QQmlContext* rootContext = ApplicationContext::RootContext;
          ... 
          QQmlComponent component(rootContext->engine(), QUrl(QStringLiteral("qrc:/login.qml")));
          
          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved