Unsolved Setting context property for individual QML UI element
-
Hello,
I am in process of learning Qt and writing it in python. So far progress is good, but I've come across one problem which I don't know how to solve. Let's look at a sample app:# foo.py from PySide2.QtCore import QObject, Property, Slot class FooController(QObject): def __init__(self, parent=None): QObject.__init__(self, parent) self.__text = "Foo" @Property(str) def text(self): return self.__text @Slot() def clickListener(self): print('Foo')
// Foo.qml import QtQuick 2.9 import QtQuick.Controls 2.2 Button { text: fooController.text onClicked: fooController.clickListener() }
# bar.py from PySide2.QtCore import QObject, Property, Slot class BarController(QObject): def __init__(self, parent=None): QObject.__init__(self, parent) self.__text = "Bar" @Property(str) def text(self): return self.__text @Slot() def clickListener(self): print('Bar')
// Bar.qml import QtQuick 2.9 import QtQuick.Controls 2.2 Button { text: barController.text onClicked: barController.clickListener() }
# main.py import sys from PySide2.QtCore import QUrl from PySide2.QtGui import QGuiApplication from PySide2.QtQml import QQmlApplicationEngine from lib.bar.bar import BarController from lib.foo.foo import FooController if __name__ == '__main__': app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() fooController = FooController() barController = BarController() engine.rootContext().setContextProperty("fooController", fooController) engine.rootContext().setContextProperty("barController", barController) engine.load(QUrl.fromLocalFile('main.qml')) if not engine.rootObjects(): sys.exit(-1) sys.exit(app.exec_())
// main.qml import QtQuick.Controls 2.2 import QtQuick 2.10 import "./foo" import "./bar" ApplicationWindow { visible: true Row { Foo {} Bar {} } }
This sample app works as intended: two buttons are displayed with names 'Foo' and 'Bar', and on click they print text in console.
What I don't like, is that currently I am setting context properties for both components in main:engine.rootContext().setContextProperty("fooController", fooController) engine.rootContext().setContextProperty("barController", barController)
This results in controllers being available globally in qml. What I want to achieve is modular approach. I can imagine that it would look like this - in main.py:
context = engine.rootContext() fooController.attachToContext(context) barController.attachToContext(context)
and corresponding methods in controllers:
def attachToContext(self, context): elemContext = context.findQmlElementByName("Foo").context() elemContext.setContextProperty("controller", self)
This way (I guess) controllers could be isolated and only accessed by the view they are set to, also this way name conflicts could be avoided. But this is theory, as I have no idea how could I achieve this - I've looked for solutions, but to no avail.
Thank you in advance for any suggestions
-
What you are looking for is two separate context and expose the object separately. If this is the case did you get a chance to look at QQmlContext documentation. It has an example expose with different contexts.
-
@dheerendra said in Setting context property for individual QML UI element:
What you are looking for is two separate context and expose the object separately. If this is the case did you get a chance to look at QQmlContext documentation. It has an example expose with different contexts.
I would like to know this as well.
The documentation only describes how to create a QQmlContext as a child of another QQmlContext, but doesn't say anything about how to retrieve or set a QQmlContext for a particular QQuickWidget.