iveus
7th February 2020, 18:05
Hi. I have a problem.
For some reason, the Q_PROPERTY NOTIFY does not work in QML. I do understand, that i'm missing something, but don't get what for a 3rd day ;)
1. I have two classes, one is BoardWiring, second is MainUi.
2. In MainUi - i have one integer, called minTimer, with the NOTIFY onMinTimerChanged().
3. The classes BoardWiring and MainUi are added in main.cpp, to use in QML.
4. The MainUi is added in private section of BoardWiring.
5. Then, I call BoardWiring.start() from QML, which calls MainUi.startTimer(), which suppose to change the static MainUi.minTimer integer to 1.
5. The MainUi.minTimer is changed, but i can't receive the NOTIFY signal in QML, it's just not notified minTimerElement.
Can someone help me with this please?
Here's the minimum of the code to reproduce:
main.cpp
#include <QDebug>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickView>
#include <QSettings>
#include "boardwiring.h"
#include "mainui.h"
#include <QString>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDp iScaling);
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLC ontexts);
QGuiApplication app(argc, argv);
QtWebEngine::initialize();
QCoreApplication::setOrganizationName("Test");
QCoreApplication::setOrganizationDomain("Test");
QCoreApplication::setApplicationName("Test");
// qmlRegisterType<BoardWiring>("io.qt.boardwiring", 1, 0, "BoardWiring");
// qmlRegisterType<MainUi>("io.qt.mainui", 1, 0, "MainUi");
BoardWiring boardwiring;
MainUi mainui;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("boardwiring", &boardwiring);
engine.rootContext()->setContextProperty("mainui", &mainui);
engine.load(QUrl(QStringLiteral("qrc:/Main.qml")));
return app.exec();
}
Main.qml
import QtQuick 2.12
import QtQuick.Controls 2.9
import QtQuick.Controls.Imagine 2.4
import QtQuick.Window 2.3
ApplicationWindow {
id: window
visible: true
width: 1280
height: 600
title: qsTr("Test")
RoundButton {
id: startButton
x: 14
y: 26
width: 230
height: 230
text: !boardwiring.isStarted ? "Start" : "Stop"
font.pointSize: 30
background: Image { source: boardwiring.isStarted? "/stop.png" : "/Start.png"; }
onClicked: {
if(!boardwiring.isStarted) {
boardwiring.start();
console.log("Main ui: " + mainui.minTimer);
} else {
boardwiring.stop();
console.log("Main ui: " + mainui.minTimer);
}
}
contentItem: Text {
text: startButton.text
font: startButton.font
opacity: 1.0
color: "black"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Text {
id: minTimerElement
x: 979
y: 291
text: mainui.minTimer // Not notifies it!
font.pixelSize: 16
}
}
boardwiring.h
#ifndef BOARDWIRING_H
#define BOARDWIRING_H
#include "mainui.h"
#include <QObject>
#include <QString>
class BoardWiring : public QObject {
Q_OBJECT
Q_PROPERTY(bool isStarted READ isStarted NOTIFY isStartedChanged WRITE
setIsStarted)
public:
explicit BoardWiring(QObject *parent = nullptr);
bool isStarted();
Q_INVOKABLE void start();
Q_INVOKABLE void setIsStarted(bool &isStarted);
signals:
void isStartedChanged(bool b_isStarted);
public slots:
private:
MainUi mainUi;
static bool b_isStarted;
};
#endif // BOARDWIRING_H
boardwiring.cpp
#include "boardwiring.h"
#include <QDebug>
#include <QString>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
bool BoardWiring::b_isStarted = 0;
bool BoardWiring::isStarted() { return b_isStarted; }
void BoardWiring::setIsStarted(bool &isStarted) {
b_isStarted = isStarted;
emit isStartedChanged(isStarted);
}
BoardWiring::BoardWiring(QObject *parent) : QObject(parent) {}
void BoardWiring::start() {
if (!b_isStarted) {
qDebug() << "STARTED";
b_isStarted = true;
mainUi.startTimer(); // Here i call the startTimer
}
emit isStartedChanged(b_isStarted);
}
void BoardWiring::stop() {
b_isStarted = false;
mainUi.stopTimer();
emit isStartedChanged(b_isStarted);
}
mainui.h
#ifndef MAINUI_H
#define MAINUI_H
#include <QObject>
#include <QString>
class MainUi : public QObject {
Q_OBJECT
Q_PROPERTY(
int minTimer READ minTimer NOTIFY minTimerChanged WRITE setMinTimer)
public:
explicit MainUi(QObject *parent = nullptr);
Q_INVOKABLE void startTimer();
int minTimer();
signals:
void minTimerChanged(const int &m_minTimer);
public slots:
void stopTimer();
void setMinTimer(int &minTimer);
private:
static int m_minTimer;
};
#endif // MAINUI_H
mainui.cpp
#include "mainui.h"
#include <QDebug>
#include <QSettings>
#include <QTimer>
int MainUi::m_minTimer = 0;
MainUi::MainUi(QObject *parent) : QObject(parent) {}
int MainUi::minTimer() { return m_minTimer; }
void MainUi::setMinTimer(int &minTimer) {
m_minTimer = minTimer;
emit minTimerChanged(minTimer);
}
void MainUi::startTimer() {
m_minTimer = 1;
setMinTimer(m_minTimer);
}
void MainUi::stopTimer() {
m_minTimer = 0;
setMinTimer(m_minTimer);
}
For some reason, the Q_PROPERTY NOTIFY does not work in QML. I do understand, that i'm missing something, but don't get what for a 3rd day ;)
1. I have two classes, one is BoardWiring, second is MainUi.
2. In MainUi - i have one integer, called minTimer, with the NOTIFY onMinTimerChanged().
3. The classes BoardWiring and MainUi are added in main.cpp, to use in QML.
4. The MainUi is added in private section of BoardWiring.
5. Then, I call BoardWiring.start() from QML, which calls MainUi.startTimer(), which suppose to change the static MainUi.minTimer integer to 1.
5. The MainUi.minTimer is changed, but i can't receive the NOTIFY signal in QML, it's just not notified minTimerElement.
Can someone help me with this please?
Here's the minimum of the code to reproduce:
main.cpp
#include <QDebug>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickView>
#include <QSettings>
#include "boardwiring.h"
#include "mainui.h"
#include <QString>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDp iScaling);
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLC ontexts);
QGuiApplication app(argc, argv);
QtWebEngine::initialize();
QCoreApplication::setOrganizationName("Test");
QCoreApplication::setOrganizationDomain("Test");
QCoreApplication::setApplicationName("Test");
// qmlRegisterType<BoardWiring>("io.qt.boardwiring", 1, 0, "BoardWiring");
// qmlRegisterType<MainUi>("io.qt.mainui", 1, 0, "MainUi");
BoardWiring boardwiring;
MainUi mainui;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("boardwiring", &boardwiring);
engine.rootContext()->setContextProperty("mainui", &mainui);
engine.load(QUrl(QStringLiteral("qrc:/Main.qml")));
return app.exec();
}
Main.qml
import QtQuick 2.12
import QtQuick.Controls 2.9
import QtQuick.Controls.Imagine 2.4
import QtQuick.Window 2.3
ApplicationWindow {
id: window
visible: true
width: 1280
height: 600
title: qsTr("Test")
RoundButton {
id: startButton
x: 14
y: 26
width: 230
height: 230
text: !boardwiring.isStarted ? "Start" : "Stop"
font.pointSize: 30
background: Image { source: boardwiring.isStarted? "/stop.png" : "/Start.png"; }
onClicked: {
if(!boardwiring.isStarted) {
boardwiring.start();
console.log("Main ui: " + mainui.minTimer);
} else {
boardwiring.stop();
console.log("Main ui: " + mainui.minTimer);
}
}
contentItem: Text {
text: startButton.text
font: startButton.font
opacity: 1.0
color: "black"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Text {
id: minTimerElement
x: 979
y: 291
text: mainui.minTimer // Not notifies it!
font.pixelSize: 16
}
}
boardwiring.h
#ifndef BOARDWIRING_H
#define BOARDWIRING_H
#include "mainui.h"
#include <QObject>
#include <QString>
class BoardWiring : public QObject {
Q_OBJECT
Q_PROPERTY(bool isStarted READ isStarted NOTIFY isStartedChanged WRITE
setIsStarted)
public:
explicit BoardWiring(QObject *parent = nullptr);
bool isStarted();
Q_INVOKABLE void start();
Q_INVOKABLE void setIsStarted(bool &isStarted);
signals:
void isStartedChanged(bool b_isStarted);
public slots:
private:
MainUi mainUi;
static bool b_isStarted;
};
#endif // BOARDWIRING_H
boardwiring.cpp
#include "boardwiring.h"
#include <QDebug>
#include <QString>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
bool BoardWiring::b_isStarted = 0;
bool BoardWiring::isStarted() { return b_isStarted; }
void BoardWiring::setIsStarted(bool &isStarted) {
b_isStarted = isStarted;
emit isStartedChanged(isStarted);
}
BoardWiring::BoardWiring(QObject *parent) : QObject(parent) {}
void BoardWiring::start() {
if (!b_isStarted) {
qDebug() << "STARTED";
b_isStarted = true;
mainUi.startTimer(); // Here i call the startTimer
}
emit isStartedChanged(b_isStarted);
}
void BoardWiring::stop() {
b_isStarted = false;
mainUi.stopTimer();
emit isStartedChanged(b_isStarted);
}
mainui.h
#ifndef MAINUI_H
#define MAINUI_H
#include <QObject>
#include <QString>
class MainUi : public QObject {
Q_OBJECT
Q_PROPERTY(
int minTimer READ minTimer NOTIFY minTimerChanged WRITE setMinTimer)
public:
explicit MainUi(QObject *parent = nullptr);
Q_INVOKABLE void startTimer();
int minTimer();
signals:
void minTimerChanged(const int &m_minTimer);
public slots:
void stopTimer();
void setMinTimer(int &minTimer);
private:
static int m_minTimer;
};
#endif // MAINUI_H
mainui.cpp
#include "mainui.h"
#include <QDebug>
#include <QSettings>
#include <QTimer>
int MainUi::m_minTimer = 0;
MainUi::MainUi(QObject *parent) : QObject(parent) {}
int MainUi::minTimer() { return m_minTimer; }
void MainUi::setMinTimer(int &minTimer) {
m_minTimer = minTimer;
emit minTimerChanged(minTimer);
}
void MainUi::startTimer() {
m_minTimer = 1;
setMinTimer(m_minTimer);
}
void MainUi::stopTimer() {
m_minTimer = 0;
setMinTimer(m_minTimer);
}