2
votes

Building off this Pyside tutorial: http://qt-project.org/wiki/PySide_QML_Tutorial_Advanced_1 http://qt-project.org/wiki/PySide_QML_Tutorial_Advanced_2 http://qt-project.org/wiki/PySide_QML_Tutorial_Advanced_3 http://qt-project.org/wiki/PySide_QML_Tutorial_Advanced_4

I am attempting to do everything in Python and not have any java script.

The only difficulty I've run into is when calling the createObject() method of a QDeclarativeComponent which is described nicely as a "Dynamic Object Management" here: http://qt-project.org/doc/qt-4.8/qdeclarativedynamicobjects.html

So here is a bare bones example that causes the error:

import sys
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtDeclarative import *

class MainWindow(QDeclarativeView):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setWindowTitle("Main Window")
        # Renders game screen
        self.setSource(QUrl.fromLocalFile('game2.qml'))
        # QML resizes to main window
        self.setResizeMode(QDeclarativeView.SizeRootObjectToView)
        # a qml object I'd like to add dynamically
        self.component = QDeclarativeComponent(QDeclarativeEngine(), QUrl.fromLocalFile("Block2.qml"))
        # check if were ready to construct the object
        if self.component.isReady():
            # create the qml object dynamically
            dynamicObject = self.component.createObject(self.rootObject())

if __name__ == '__main__':
    # Create the Qt Application
    app = QApplication(sys.argv)
    # Create and show the main window
    window = MainWindow()
    window.show()
    # Run the main Qt loop
    sys.exit(app.exec_())

With main window QML file contents ("game2.qml"):

import QtQuick 1.0

Rectangle {
    id: screen

    width: 490; height: 720

    SystemPalette { id: activePalette }
}

And QML object I'd like to dynamically construct ("Block2.qml"):

import QtQuick 1.0

Rectangle {
    id: block
}

When I run this code, it crashes at:

dynamicObject = self.component.createObject(self.rootObject())

with:

TypeError: Unknown type used to call meta function (that may be a signal): QScriptValue

I understand the parent must be a QObject but otherwise I'm not entirely sure from the docs what more it should constitute: http://srinikom.github.io/pyside-docs/PySide/QtDeclarative/QDeclarativeComponent.html

This isn't an issue in C++ according to: https://qt-project.org/forums/viewthread/7717

It is clearly only an issue in Pyside currently.

Any idea what might be causing this issue? Potential bug?

1

1 Answers

0
votes

A work around is to rely on javascript for object creation while everything else is python. In this implementation you pass the qml file of the component and its parent to the javascript implementation that creates the component. It does a basic construction of the object. Would be ideal having pure python solution though for brevity.

import sys
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtDeclarative import *

class MainWindow(QDeclarativeView):

def __init__(self, parent=None):
    super(MainWindow, self).__init__(parent)
    self.setWindowTitle("Main Window")
    # Renders game screen
    self.setSource(QUrl.fromLocalFile('game2.qml'))
    # QML resizes to main window
    self.setResizeMode(QDeclarativeView.SizeRootObjectToView)
    # a qml object I'd like to add dynamically
    parent = self.rootObject()
    view = QDeclarativeView()
    view.setSource(QUrl.fromLocalFile("comp_create.qml"))
    block = view.rootObject().create("Block2.qml", parent)
    print block
    block.x = 100
    block.y = 200
    # prove that we created the object
    print block.x, block.y

if __name__ == '__main__':
    # Create the Qt Application
    app = QApplication(sys.argv)
    # Create and show the main window
    window = MainWindow()
    window.show()
    # Run the main Qt loop
    sys.exit(app.exec_())

The only added QML is a component creator that uses javascript to create objects since Pyside currently wont work ("comp_create.qml"):

import QtQuick 1.0

Item {
    id: creator

     function create(qml_fname, parent) {
         // for a given qml file and parent, create component
         var comp = Qt.createComponent(qml_fname);
         if (comp.status == Component.Ready) {
             // create the object with given parent
             var ob = comp.createObject(parent);
             if (ob == null) {
                 // Error Handling
                 console.log("Error creating object");
             }
             return ob
         } else if (component.status == Component.Error) {
             // Error Handling
             console.log("Error loading component:", component.errorString());
         }
         else {
             component.statusChanged.connect(finishCreation);
         }
         return null
     } 
}

Note, borrowed this code mostly from: http://qt-project.org/doc/qt-4.8/qdeclarativedynamicobjects.html