C++ PROPERTY changed() to QML
-
Hi all,
I lost my way in C++ PROPERTY to connect to QML.
What I did already.- Created main.cpp. main.cpp calls backend_qml.
- Backend_qml calls HWButton.
- In the backend_qml there is a Q_PROPERTY which shares a page number to QML.
- If a Hardware button is pushed, the button changes the page number and the page needs to change in QML.
- (need to add this: send some more variables to the QML)
#include <backend_qml.h> #include <system_control.h> #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QtQml> #include <QQmlContext> #include <QQmlEngine> int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); backend_qml bqml; system_control cc_system; QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("backend_qml", &bqml); //qmlRegisterType<backend_qml>("PropertyBinding", 1, 0, "PropertyBinding"); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
When I run:
QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("backend_qml", &bqml);
I can change the page number, but I'm not able to get the signal in QML when the PROPERTY has CHANGED.
When I run:
qmlRegisterType<backend_qml>("PropertyBinding", 1, 0, "PropertyBinding");
The application runs, but no data is transfered to QML. I think this is normal as I didn't make a instance of backend_qml.
Below the backend_qml.h and backend_qml.cpp
#ifndef BACKEND_QML_H #define BACKEND_QML_H #include <QObject> #include <QScopedPointer> #include <QDebug> #include "hwbutton.h" class backend_qml : public QObject { Q_OBJECT Q_PROPERTY(int page READ page WRITE setPage NOTIFY pageChanged) public: explicit backend_qml(QObject *parent = nullptr); int page() const {qDebug() << QString::number(m_page); return m_page;} signals: void pageChanged(); public slots: void setPage(int page); private: int m_page; HWButton hwbutton; }; #endif // BACKEND_QML_H
#include "backend_qml.h" backend_qml::backend_qml(QObject *parent) : QObject(parent) { qDebug()<< "app is running"; connect(&hwbutton,SIGNAL(buttonPushed(int)),this,SLOT(setPage(int))); } void backend_qml::setPage(int page) { qDebug() << "page changer called" ; m_page = page; emit pageChanged(); // trigger signal if page is changed }
So the main goal is when setPage() is called, a function in qml is called together with the new pagenumber.
I hope somebody is able to point me in the correct direct. I got really confussed.
Thanks in advance,
Kind regards,
TMJJ************** EDIT **************
QML
I have multiple qml files.
In the main, I just have some global variables. here I also run my Main_Screen{}
import QtQuick 2.6 import QtQuick.Window 2.2 Window { visible: true width: 800 height: 480 title: qsTr("Hello World") property string workspace_background_color : "#FFFFFF" property string errorheader_background_color : "#FFFFFF" Main_screen{ } }
In the main_screenForm.ui.qml I have the following:
import QtQuick 2.4 import QtQuick.Layouts 1.3 import QtQuick.Controls 1.4 import "MaterialDesignIconGlyphs.js" as MaterialGlyphs Item { width: 800 height: 480 property alias workspace: workspace property alias pushbutton1: pushbutton1 property alias pushbutton2: pushbutton2 property alias pushbutton3: pushbutton3 property alias pushbutton4: pushbutton4 property alias pushbutton5: pushbutton5 property alias mouse: mouse property alias button2_pushed: button2_pushed property alias button3_pushed: button3_pushed property alias button4_pushed: button4_pushed property alias button5_pushed: button5_pushed property alias workspace_stacked_view: workspace_stacked_view property string leftbar_pushed_button_indicator_color: "#FF6110" GridLayout { id: maingrid columnSpacing: 0 rowSpacing: 0 anchors.fill: parent anchors.margins: 0 columns: 2 rows: 2 Rectangle { id: companyheader Layout.preferredHeight: 80 Layout.preferredWidth: 100 Layout.margins: 0 color: "#014088" Image { id: companylogo anchors.fill: parent fillMode: Image.PreserveAspectFit source: "qrc:/resource/img/Company/Logo.png" } MouseArea { id: pushbutton1 anchors.fill: parent } } Rectangle { id: errorheader Layout.preferredHeight: 80 Layout.fillWidth: true color: "#FF6110" Text { id: tetlol x: 23 y: 19 width: 112 height: 42 text: backend_qml.page font.pixelSize: 12 } } ... StackView { id: workspace_stacked_view initialItem: homepage anchors.fill: parent } ...
Like this I'm able to print the page number inside my header. So this works fine.
Now I also have a stackview. Here I want to change the page when a hardware button is pushed.
So As explained above, I tried to use:qmlRegisterType<backend_qml>("PropertyBinding", 1, 0, "PropertyBinding");
Then in my Main_screen.qml I did like this:
import QtQuick 2.4 import QtQml 2.2 import PropertyBinding 1.0 import "qrc:/pages/" // import qml file from different resource folder Main_screenForm { button2_pushed.visible:true button3_pushed.visible:false button4_pushed.visible:false button5_pushed.visible:false mouse { onClicked: console.info("pushed mouse") } function pagechanger(n) { switch(n){ case 1: button2_pushed.visible=true button3_pushed.visible=false button4_pushed.visible=false button5_pushed.visible=false workspace_stacked_view.push(homepage);break; case 2: button2_pushed.visible=false button3_pushed.visible=true button4_pushed.visible=false button5_pushed.visible=false workspace_stacked_view.push(settingpage);break; case 3: button2_pushed.visible=false button3_pushed.visible=false button4_pushed.visible=true button5_pushed.visible=false workspace_stacked_view.push(diagnosepage);break; case 4: button2_pushed.visible=false button3_pushed.visible=false button4_pushed.visible=false button5_pushed.visible=true;break; } } pushbutton2{ onClicked: { console.info("touch pushbutton2 clicked"); pagechanger(1); } } pushbutton3{ onClicked: { console.info("touch pushbutton3 clicked"); pagechanger(2); } } pushbutton4{ onClicked: { console.info("touch pushbutton4 clicked"); pagechanger(3); } } pushbutton5{ onClicked: { console.info("touch pushbutton5 clicked"); pagechanger(4); } } Component{ id:homepage HomePage{ //anchors.fill:parent } } Component{ id:settingpage SettingPage{ //anchors.fill:parent } } Component{ id:diagnosepage DiagnosePage{ //anchors.fill:parent } } // HERE IN NEED TO CALL FUNCTION pagechanger! } /*##^## Designer { D{i:0;autoSize:true;height:480;width:640} } ##^##*/
I hope it is still clear what I try to reach.
Kind regards
-
@TMJJ001 I think you are doing too complicate and not in the cleanest way. Here some hints:
- C++ class names should be UpperCamelCase, to respect common Qt/QML coding rules
- Instance names should be lowerCamelCase, again to respect common Qt/QML coding rules
- try to think simple, if you fight against the framework, then you are doing something in the wrong way
- I would also strongly recommend you to read the Qt documentation: Integrating QML and C++
So, now how I would do it.
The backend class:#ifndef BACKENDQML_H #define BACKENDQML_H #include <QObject> class BackendQml : public QObject { Q_OBJECT Q_PROPERTY(int page READ page WRITE setPage NOTIFY pageChanged) public: explicit BackendQml(QObject *parent = nullptr): QObject(parent), m_page(0) {} int page() const { return m_page; } signals: void pageChanged(int page); public slots: void setPage(int page) { if(m_page != page) { m_page = page; emit pageChanged(page); } } private: int m_page; }; #endif // BACKENDQML_H
Expose the global variable to QML Engine:
QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("backendQml", &bqml);
Then in QML (Main_Screen):
import QtQuick 2.6 import QtQuick.Window 2.2 Window { visible: true width: 800 height: 480 title: qsTr("Hello World") property string workspace_background_color : "#FFFFFF" property string errorheader_background_color : "#FFFFFF" readonly property int currentPage: backendQml.page onCurrentPageChanged { console.log("Current page is " + currentPage) } .. }
And when changing page, simply change you pagechanger() function to add
backendQml.page=n
, like this:function pagechanger(n) { backendQml.page=n switch(n){ ... } }