Using anything from QtQuick.Controls throws a protected module error - python

I am getting these errors, when i try to launch the program:
plugin cannot be loaded for module, cannot install type into protected module
Platform:
Python 3.8
PyQt5 5.15.0
Visual Studio Community 2019
Windows 10 Pro 1909
main python file (the whole thing is pretty much the example from here: https://codeloop.org/pyqt5-creating-first-window/ )
import numpy
import os
import sys
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtWidgets import QApplication
def main():
app =QApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.load(os.path.join(os.path.dirname(__file__), "MainApp.qml"))
if not engine.rootObjects():
return -1
return app.exec_()
if __name__ == '__main__':
main();
The corresponding QML File "MainApp.qml":
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick 2.15
Window {
visible:true
width:600
height:400
color:"yellow"
title: "PyQt5 QML Window"
Button {
text: "Something"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
Without using anything from QtQuick.Controls, it works, but as soon as i add the button, it generates these errors:
QQmlApplicationEngine failed to load component
file:///C:/Users/elano/Source/Repos/Projekt-1-SS2020/Projekt-1-SS2020/MainApp.qml:15:5: Type Button unavailable
file:///C:/Users/elano/vpqt/lib/site-packages/PyQt5/Qt/qml/QtQuick/Controls.2/qmldir: plugin cannot be loaded for module "QtQuick.Controls": Cannot install type 'VerticalHeaderView' into protected module 'QtQuick.Controls' version '2'
<Unknown File>: Cannot install type 'HorizontalHeaderView' into protected module 'QtQuick.Controls' version '2'
<Unknown File>: Cannot install element 'SplitHandle' into protected module 'QtQuick.Controls' version '2'
...
The file it tries to find (qmldir) does exist, and contains this:
module QtQuick.Controls
plugin qtquickcontrols2plugin
classname QtQuickControls2Plugin
depends QtQuick.Templates 2.5
designersupported
Does anyone know what is going on here? Is more information needed?

Okay, now i feel stupid. I already kinda had my answer in my code, but since it didn't get Pyside2 to work, i commented it out...
The problem was, that an environment variable was not set properly. Adding this after my import statements in my main file fixed it:
dirname = os.path.dirname(PyQt5.__file__)
plugin_path = os.path.join(dirname, 'plugins', 'platforms')
os.environ['QML2_IMPORT_PATH'] = os.path.join(dirname, 'qml')
No tutorial i found has ever mentioned this. Great.

Related

Failed to build graphics pipeline state in qt quick application

I have a qt quick pyside application .I had a question before,but now another proplem is there .Just a empty window appears and then in application window I see below message.Although I have another qt quick application that I written that in c++ and there is no problem displaying it, this message is displayed!,This application is in python(pyside6)
I use Qt 6.0.2,Python 3.9.2,Qt Creator 4.14.1 and Pyside6
Failed to create vertex shader: Error 0x80070057: The parameter is incorrect.
Failed to build graphics pipeline state
*main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
id:mainWindow
width: 1000
height: 580
visible: true
title: qsTr("JooyaTrader")
Rectangle{
width: 152
height: 62
anchors.fill: parent
color: "red"
}
}
main.py
import sys,os
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
import PySide6
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
The problem is caused because the backend that Qt Quick uses for rendering does not work for your case, either because there are missing libraries or the version is not according to what Qt expects. In that one solution is to set the QT_QUICK_BACKEND in "software" making the rendering do it Qt Quick 2D Renderer:
os.environ["QT_QUICK_BACKEND"] = "software"
app = QGuiApplication(sys.argv)
For more information read Scene Graph Adaptations.

Using Python class files in QML

I have a main.qml file that look like below
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
TextField {
id:textarea
anchors.centerIn: parent
Button {
text: "Click Me"
anchors.leftMargin: 34
id:textareabutton
y: 0
anchors.left:textarea.right
onClicked: {
someclass.say(textarea.text)
}
}
}
TextField {
id:textarea2
anchors.horizontalCenterOffset: 0
anchors.topMargin: 37
anchors.top: textarea.bottom
anchors.horizontalCenter: textarea.horizontalCenter
}
Connections {
target: someclass
onToPython : {
textarea2.text = say
}
}
}
i have a python class file which i have added using add file option in qtcreator, when i run main.qml i am getting errors related to the classes being undefined as below
qrc:/main.qml:33:5: QML Connections: Cannot assign to non-existent property "onToPython"
qrc:/main.qml:34: ReferenceError: someclass is not defined
qrc:/main.qml:22: ReferenceError: someclass is not defined
I have the external tools configured in the Qt creator for python and when i run through it,it works. However it is not working when i run main.qml. What am i missing, how can i make use of the python class file.
below is the python file that invokes the QML , if i run from python it works, i want to run qml file and invoke this class
import sys
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtCore import QObject,pyqtSignal,pyqtSlot
class someclassr(QObject):
def __init__(self):
QObject.__init__(self)
toPython=pyqtSignal(str, arguments=["say"])
#pyqtSlot(str)
def say (self,name):
word= "hi " + name
self.toPython.emit(word)
app = QGuiApplication(sys.argv)
engine=QQmlApplicationEngine()
classloader=someclassr()
engine.rootContext().setContextProperty('someclass',classloader)
engine.load('main.qml')
engine.quit.connect(app.quit)
sys.exit(app.exec_())
Short answer: There's no built-in integration between QML and Python. I'm not sure why one'd assume that there was, but there really isn't. Qt Creator is a multi-language IDE, and its support for Python doesn't imply that QML and Python are integrated.
Having said that, Python classes can be easily integrated with Qt and QML using PyQt. If you don't want to depend on PyQt, you can integrate the two manually by writing adapter classes that call into the Python runtime that your application would link with.

qml file can't call function to pyd file

There is qml file can't call function to pyd file problem.
There are several files:
i. main.py -> python.exe run entry
ii. mainWidget.py -> show MyItem.qml ui and setContextProperty to MyItem.qml
iii. MyItem.qml -> when you click mouse area will call MyObect function "cppMethod" and "cppSlot" in mainWidget.py
iv. setup.py -> build extension file to generate pyd used
v. mainWidget.pyd -> generate by Cython
In mainWidget.py, there is MyObject class, in this class, function "cppMethod" and "cppSlot" will print log on python.exe
And then I call "setContextProperty" function to register "myobject" to MyItem.qml so that MyItem.qml will recognize "myobject" object.
When I run main.py on python.exe, it will show a widget.
Try to click in this widget, it will call MyObect function "cppMethod" and "cppSlot". It worked!!!
It will show:
qml: start
call the c++ method with Hello from QMLTest
call the c++ slot with 12345
qml: end
After that, I try to protect the code, so I use Cython(with setup.py) to generate file "mainWidget.pyd".
So I replace mainWidget.pyd for mainWidget.py.
When I run main.py with python.exe with "mainWidget.pyd", I click mouse area in the widget, it will show
"TypeError: Property 'cppMethod' of object MyObject(0x21822d07430) is not a function".
It means MyItem.qml doesn't recognize "myobject".
Is there any way to fix this problem?? How to fix this problem??
ps. I use Python version 3.6.2, Qt version 5.6.2
main.py
import mainWidget
widget = mainWidget.main()
mainWidget.py
import os
import sys
import PySide2
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import QApplication, QWidget
from PySide2.QtQuickWidgets import *
class MyObject(PySide2.QtCore.QObject):
def __init__(self, parent=None):
super(MyObject, self).__init__(parent)
#PySide2.QtCore.Slot(str)
def cppMethod(self, msg):
print ("call the c++ method with ",msg)
#PySide2.QtCore.Slot(int)
def cppSlot(self, number):
print ("call the c++ slot with", number)
def main():
app = QApplication(sys.argv)
view = QQuickWidget()
myclass = MyObject()
view.rootContext().setContextProperty("myObject",myclass)
relativeUrl = QUrl(".//MyItem.qml")
view.setSource(relativeUrl)
view.show()
sys.exit(app.exec_())
MyItem.qml
import QtQuick 2.5
import QtQuick.Controls 1.5
import QtQuick.Layouts 1.3
import QtQuick.Controls.Styles 1.4
import QtQml 2.2
Item {
width: 100; height: 100
MouseArea {
anchors.fill: parent
onClicked: {
console.log("start")
myObject.cppMethod("Hello from QML")
myObject.cppSlot(12345)
console.log("end")
}
}
}
setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("mainWidget.py")
)
Cython does not implement the MOC, so QML can not invoke the methods (if the generated .c is reviewed, it is observed that everything is implemented except the #Slot that the MOC creates).
A workaround is to separate the code that uses the slot and use cython in that part after you import and use the compiled code in the slot.

How to convert QJSValue to Python list in Python and QML?

I hava a Python file ang a QML file. i get value in Python file from QML, and the type of value is QJSValue , i want to convert it to Python list. i don't know how to do it.
following is my code.
test.python
#!/usr/bin/env python
# encoding: utf-8
from PyQt5.QtCore import QUrl, QObject, pyqtSlot,QVariant
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQuick import QQuickView
from PyQt5.QtQml import QJSValue
class MyMain(QObject):
#pyqtSlot(QJSValue)
def get_value(self,value):
print(value,type(value))
if __name__ == '__main__':
path = 'test.qml'
app = QApplication([])
view = QQuickView()
con = MyMain()
context = view.rootContext()
context.setContextProperty("con",con)
view.engine().quit.connect(app.quit)
view.setSource(QUrl(path))
view.show()
app.exec()
test.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
Button {
text: "click"
onClicked: {
con.get_value([{"name":"a","text":"1"},{"name":"b","text":"2"}])
}
}
I realize this question is extremely old, but I thought I'd post how I came to the solution in case someone else stumbles upon it via Google.
While it isn't technically a direct conversion to a python list, what I found useful was to do myQJSValueInstance.toVariant() which converts the instance to a QVariant. I could then use the object as needed (e.g., iterating through it as if it were a normal python list).

Utilizing QtQuick Controls from PyQt5

First of all, I tried to use QtQuick from PySide. The latest PySide as of today wraps Qt 4.8, which doesn't have an actively developed desktop components. (colibri is there, but that's not for desktop, and it's buggy).
PyQt seems to win here, since the latest version (5.2.1 as of today), wraps Qt 5, which has QtQuick controls ready.
I've looked at many of the examples under Lib/site-packages/PyQt5/examples/quick, all of them work, but none of them use QtQuick Controls.
I am trying a very simple qml here:
//main.qml
import QtQuick.Controls 1.2
ApplicationWindow {
title: "My Application"
Button {
text: "Push Me"
anchors.centerIn: parent
}
}
and a python file:
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQml import QQmlApplicationEngine
import sys
if __name__ == "__main__":
app = QApplication(sys.argv)
engine = QQmlApplicationEngine("main.qml")
engine.quit.connect(app.quit)
sys.exit(app.exec_())
but i'm having this error:
.../main.qml:1 module "QtQuick.Controls" version 1.2 is not installed
Can I use QtQuick Controls from PyQt5?. And if so, how?. I can't find it anywhere.
Did you try to use QtQuick.Controls 1.0, it works fine on my system

Categories