Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. QML working in QQuickView, but not in custom QQuickWindow
Qt 6.11 is out! See what's new in the release blog

QML working in QQuickView, but not in custom QQuickWindow

Scheduled Pinned Locked Moved Solved QML and Qt Quick
6 Posts 2 Posters 3.7k Views 1 Watching
  • 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.
  • K Offline
    K Offline
    kloffy
    wrote on last edited by
    #1

    My aim is to use QML for GUI on top of some custom rendering that I am doing in OpenGL. Before going into that, I thought it would be good to get a better understanding of QML. Therefore, I thought I might start by implementing my own version of QQuickView on top of QQuickWindow (slowly working my way deeper into the workings of QML). However, while doing so, I quickly ran into a problem with the following QML:

    import QtQuick 2.5
    import QtQuick.Controls 1.4
    
    Item {
    	anchors.fill: parent
    
    	ListModel {
    		id: fruitModel
    
    		ListElement {
    			title: "Apple"
    			page: "Banana"
    		}
    		ListElement {
    			title: "Orange"
    			page: "Banana"
    		}
    		ListElement {
    			title: "Banana"
    			page: "Banana"
    		}
    	}
    
    	ListView {
    		anchors.fill: parent
    		model: fruitModel
    		delegate: Rectangle{
    			width: parent.width; height: 80
    			color: "red"
    			Text {
    				anchors.fill: parent
    				color: "black"
    				text: title
    			}
    		}
    	}
    }
    

    This is a pretty simple scene that works perfectly well if I display it in a QQuickView. However, if I use my custom window, only the first list item is displayed. Can anybody point me towards what is missing in my QQuickWindow subclass to make this work?

    #! /usr/bin/python3
    
    import os
    import sys
    
    from PyQt5 import QtCore, QtGui, QtNetwork, QtQml, QtQuick, QtWidgets
    
    def application_path(*paths):
        return os.path.join(os.path.dirname(os.path.realpath(__file__)), *paths)
    
    class MainWindow(QtQuick.QQuickWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
    
            self._engine = QtQml.QQmlEngine(self)
            if not self._engine.incubationController():
                self._engine.setIncubationController(self.incubationController())
            
            self._engine.quit.connect(QtWidgets.QApplication.instance().quit)
        
        def setSource(self, url):
            context = QtQml.QQmlContext(self._engine)
    
            component = QtQml.QQmlComponent(self._engine)
            component.loadUrl(url)
    
            if component.isError():
                logger.error(component.errorString())
                return
    
            obj = component.create(context)
    
            if component.isError():
                logger.error(component.errorString())
                return
    
            if isinstance(obj, QtQuick.QQuickItem):
                obj.setParentItem(self.contentItem())
                self._root = obj
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        
        #view = QtQuick.QQuickView()
        view = MainWindow() 
        view.setSource(QtCore.QUrl.fromLocalFile(application_path("main.qml")))
        view.resize(800, 600)
        view.show()
        
        sys.exit(app.exec_())
    
    p3c0P 1 Reply Last reply
    0
    • K kloffy

      My aim is to use QML for GUI on top of some custom rendering that I am doing in OpenGL. Before going into that, I thought it would be good to get a better understanding of QML. Therefore, I thought I might start by implementing my own version of QQuickView on top of QQuickWindow (slowly working my way deeper into the workings of QML). However, while doing so, I quickly ran into a problem with the following QML:

      import QtQuick 2.5
      import QtQuick.Controls 1.4
      
      Item {
      	anchors.fill: parent
      
      	ListModel {
      		id: fruitModel
      
      		ListElement {
      			title: "Apple"
      			page: "Banana"
      		}
      		ListElement {
      			title: "Orange"
      			page: "Banana"
      		}
      		ListElement {
      			title: "Banana"
      			page: "Banana"
      		}
      	}
      
      	ListView {
      		anchors.fill: parent
      		model: fruitModel
      		delegate: Rectangle{
      			width: parent.width; height: 80
      			color: "red"
      			Text {
      				anchors.fill: parent
      				color: "black"
      				text: title
      			}
      		}
      	}
      }
      

      This is a pretty simple scene that works perfectly well if I display it in a QQuickView. However, if I use my custom window, only the first list item is displayed. Can anybody point me towards what is missing in my QQuickWindow subclass to make this work?

      #! /usr/bin/python3
      
      import os
      import sys
      
      from PyQt5 import QtCore, QtGui, QtNetwork, QtQml, QtQuick, QtWidgets
      
      def application_path(*paths):
          return os.path.join(os.path.dirname(os.path.realpath(__file__)), *paths)
      
      class MainWindow(QtQuick.QQuickWindow):
          def __init__(self):
              super(MainWindow, self).__init__()
      
              self._engine = QtQml.QQmlEngine(self)
              if not self._engine.incubationController():
                  self._engine.setIncubationController(self.incubationController())
              
              self._engine.quit.connect(QtWidgets.QApplication.instance().quit)
          
          def setSource(self, url):
              context = QtQml.QQmlContext(self._engine)
      
              component = QtQml.QQmlComponent(self._engine)
              component.loadUrl(url)
      
              if component.isError():
                  logger.error(component.errorString())
                  return
      
              obj = component.create(context)
      
              if component.isError():
                  logger.error(component.errorString())
                  return
      
              if isinstance(obj, QtQuick.QQuickItem):
                  obj.setParentItem(self.contentItem())
                  self._root = obj
      
      if __name__ == '__main__':
          app = QtWidgets.QApplication(sys.argv)
          
          #view = QtQuick.QQuickView()
          view = MainWindow() 
          view.setSource(QtCore.QUrl.fromLocalFile(application_path("main.qml")))
          view.resize(800, 600)
          view.show()
          
          sys.exit(app.exec_())
      
      p3c0P Offline
      p3c0P Offline
      p3c0
      Moderators
      wrote on last edited by
      #2

      Hi @kloffy and Welcome,

      I'm not aware of PyQt so I'm not sure what is causing that problem in that case. But I replicated the same code using C++ and it worked as expected. All 3 items are shown. Following is what I tried:
      MainWindow.cpp

      MainWindow::MainWindow()
      {
          QQmlEngine *eng = new QQmlEngine(this);
          eng->setIncubationController(incubationController());
      
          QQmlContext *con = new QQmlContext(eng);
      
          QQmlComponent *comp = new QQmlComponent(eng);
          comp->loadUrl(QUrl("qrc:/main.qml"));
      
          QQuickItem *obj = qobject_cast<QQuickItem*>(comp->create(con));
          obj->setParentItem(contentItem());
      }
      

      main.cpp

      QGuiApplication app(argc, argv);
      
      MainWindow win;
      win.resize(800,600);
      win.show();
      
      return app.exec();
      

      157

      1 Reply Last reply
      1
      • K Offline
        K Offline
        kloffy
        wrote on last edited by
        #3

        Thank you for testing the code in C++, I should have probably tried that myself. Your response has led me towards a solution. It appears that the problem is indeed specific to PyQt5, and in particular I have a feeling it might be related to object lifetimes. Something might be getting destroyed before it should be, which has me a bit worried about the robustness of PyQt5 in general. I can make the example work by keeping a reference to the context in a member of MainWindow, i.e.:

        self._context = QtQml.QQmlContext(self._engine)
        

        I was under the impression that in Qt's ownership model, the QQmlContext would be kept alive by its parent the QQmlEngine. I am really puzzled by what is going on, but I suppose in order to get clarity I will have to consult the PyQt5 guys.

        1 Reply Last reply
        0
        • K Offline
          K Offline
          kloffy
          wrote on last edited by
          #4

          Oh, mea culpa to the PyQt5 guys. I just saw that the parent is passed as the second parameter to QQmlContext. If I pass QQmlEngine twice, it also works:

          context = QtQml.QQmlContext(self._engine, self._engine)
          

          On the other hand, in that case I am a bit confused as to why this is not an issue in C++.

          p3c0P 1 Reply Last reply
          0
          • K kloffy

            Oh, mea culpa to the PyQt5 guys. I just saw that the parent is passed as the second parameter to QQmlContext. If I pass QQmlEngine twice, it also works:

            context = QtQml.QQmlContext(self._engine, self._engine)
            

            On the other hand, in that case I am a bit confused as to why this is not an issue in C++.

            p3c0P Offline
            p3c0P Offline
            p3c0
            Moderators
            wrote on last edited by
            #5

            @kloffy I too have no idea about the implementation :) You can try asking it on the mailing lists.
            http://lists.qt-project.org/mailman/listinfo/interest
            http://lists.qt-project.org/mailman/listinfo
            The Qt developers might know the exact reason behind these internals.

            157

            1 Reply Last reply
            1
            • K Offline
              K Offline
              kloffy
              wrote on last edited by
              #6

              Thanks again, the mailing list will come in handy, no doubt. As far as the original problem goes, I think it can be considered resolved! :)

              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